package com.uinnova.product.eam.service.impl;

import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.binary.core.exception.BinaryException;
import com.binary.core.util.BinaryUtils;
import com.binary.jdbc.Page;
import com.uinnova.product.eam.base.util.EamUtil;
import com.uinnova.product.eam.comm.model.es.EamDiagramRelease;
import com.uinnova.product.eam.config.Env;
import com.uinnova.product.eam.db.bean.DiagramChangeData;
import com.uinnova.product.eam.model.ArtifactConstraintVo;
import com.uinnova.product.eam.model.EamArtifactElementVo;
import com.uinnova.product.eam.model.asset.EamCiRltDTO;
import com.uinnova.product.eam.model.asset.EamReleaseHistoryDTO;
import com.uinnova.product.eam.model.bm.DiagramPrivateAndDesginData;
import com.uinnova.product.eam.model.dto.ElementDto;
import com.uinnova.product.eam.service.ESDiagramSvc;
import com.uinnova.product.eam.service.FxDiagramSvc;
import com.uinnova.product.eam.service.ICISwitchSvc;
import com.uinnova.product.eam.service.IEamArtifactColumnSvc;
import com.uinnova.product.eam.service.bm.impl.FlowModelMergePreProcessor;
import com.uinnova.product.eam.service.es.*;
import com.uinnova.product.eam.service.handler.PushFacadeService;
import com.uinnova.product.eam.service.utils.DataModelDiagramUtil;
import com.uinnova.product.vmdb.comm.model.ci.*;
import com.uinnova.product.vmdb.comm.model.rlt.CCcCiRlt;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiClassInfo;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiInfo;
import com.uinnova.product.vmdb.provider.rlt.bean.CcCiRltInfo;
import com.uinnova.project.api.diagram.v2.client.ESDiagramApiClient;
import com.uinnova.project.base.diagram.comm.diagram.*;
import com.uinnova.project.base.diagram.comm.model.*;
import com.uinnova.project.db.eam.ESDiagramDao;
import com.uinnova.project.db.eam.ESDiagramLinkDao;
import com.uinnova.project.db.eam.ESDiagramNodeDao;
import com.uinnova.project.db.eam.ESDiagramSheetDao;
import com.uinnova.project.service.diagram.IEamDiagramSvc;
import com.uinnova.project.service.eam.IEamShareDiagramSvc;
import com.uino.api.client.cmdb.ICIClassApiSvc;
import com.uino.api.client.permission.IUserApiSvc;
import com.uino.bean.cmdb.base.*;
import com.uino.bean.cmdb.business.BindCiRltRequestDto;
import com.uino.bean.cmdb.query.ESCISearchBean;
import com.uino.bean.cmdb.query.ESRltSearchBean;
import com.uino.bean.permission.base.SysUser;
import com.uino.bean.permission.query.CSysUser;
import com.uino.dao.cmdb.ESCIAttrTransConfigSvc;
import com.uino.dao.cmdb.ESCIClassSvc;
import com.uino.dao.cmdb.ESRltClassSvc;
import com.uino.dao.util.ESUtil;
import com.uino.service.permission.microservice.IUserSvc;
import com.uino.tarsier.tarsiercom.util.IdGenerator;
import com.uino.util.sys.CheckAttrUtil;
import com.uino.util.sys.SysUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 通用架构设计视图处理业务层
 *
 * @author ch
 * @date 2021/11/3
 */
@Service
@Slf4j
public class FxDiagramSvcImpl implements FxDiagramSvc {

    @Autowired
    ESDiagramApiClient diagramApiClient;

    @Autowired
    ESDiagramNodeDao iamsEsDiagramNodeDao;

    @Autowired
    ESDiagramLinkDao iamsEsDiagramLinkDao;

    @Autowired
    IamsESCIPrivateSvc iamsESCIPrivateSvc;

    @Autowired
    IamsESCIDesignSvc iamsESCIDesignSvc;

    @Autowired
    IamsESCIRltPirvateSvc iamsESCIRltPirvateSvc;

    @Autowired
    ESCIClassSvc esciClassSvc;

    @Autowired
    ESRltClassSvc esRltClassSvc;

    @Autowired
    IUserApiSvc userApiSvc;

    @Autowired
    IEamArtifactColumnSvc iEamArtifactColumnSvc;

    @Autowired
    IamsCIRltSwitchSvc ciRltSwitchSvc;

    @Resource
    ICISwitchSvc ciSwitchSvc;

    @Autowired
    ICIClassApiSvc iciClassApiSvc;

    @Autowired
    ESDiagramDao esDiagramDao;

    @Autowired
    ESDiagramSvc esDiagramSvc;

    @Autowired
    private IEamShareDiagramSvc shareDiagramSvc;

    @Autowired
    IamsCIRltDesignSvc iamsCIRltDesignSvc;

    @Autowired
    IamsCIRltPrivateSvc iamsCIRltPrivateSvc;

    @Resource
    private IEamDiagramSvc eamDiagramSvc;

    @Autowired
    private ESDiagramSheetDao esDiagramSheetDao;

    @Autowired
    private IamsESCIHistoryDesignSvc iamsESCIHistoryDesignSvc;

    @Autowired
    private IamsESCIRltInfoHistoryDesignSvc iamsESCIRltInfoHistoryDesignSvc;

    @Autowired
    private IamsESCIRltPirvateSvc esCIRltPirvateSvc;

    @Autowired
    PushFacadeService pushFacadeService;

    @Autowired
    private ESCIAttrTransConfigSvc attrConfigSvc;
    @Autowired
    private FlowModelMergePreProcessor flowModelMergePreProcessor;
    @Autowired
    private IUserSvc userSvc;

    /**
     * 通用发布校验步骤
     */
    public static final Integer PRIMARY_KEY_CHECK = 1;      // 主键冲突
    public static final Integer PRODUCT_NUM_CHECK = 2;      // 制品数量
    public static final Integer REQUIRED_FIELD_CHECK = 3;      // 必填项校验
    public static final Integer DIAGRAM_VERSION_CHECK = 4;      // 视图数据版本
    public static final Integer CI_VERSION_CHECK = 5;      // CI版本校验

    /**
     * ==========用户检核完成图上数据 确认绑定成功关系 之后进行版本冲突校验========
     * <p>
     * 当前视图数据版本冲突检核
     *
     * @return
     */
    @Override
    public List<DiagramChangeData> getVersionChangeCIByDEnergyId(String dEnergyId) {
        List<DiagramChangeData> versionChangeData = new ArrayList<>();    // 返回数据

        List<ESDiagramDTO> esDiagramDTOS = this.queryDiagramInfoByIds(Collections.singletonList(dEnergyId));        // 查询视图数据
        SysUser userInfoByOwnerCode = this.getUserInfoByOwnerCode(esDiagramDTOS.get(0).getDiagram().getOwnerCode());
        DiagramPrivateAndDesginData privateAndDesginDataByDEnergyId = this.getPrivateAndDesginDataByDEnergyId(esDiagramDTOS, userInfoByOwnerCode);       // 获取视图数据

        // 读取视图 CI 数据 判断版本
        List<CcCiInfo> privateCiInfos = privateAndDesginDataByDEnergyId.getPrivateCiInfos();
        List<CcCiInfo> desginCiInfos = privateAndDesginDataByDEnergyId.getDesginCiInfos();

        if (CollectionUtils.isEmpty(desginCiInfos)) {
            return versionChangeData;       // 设计库数据为空 视图数据都为新建 不存在版本冲突
        }

        // 判断私有库与设计库数据是否存在版本冲突
        Map<String, CcCiInfo> desginCodeAndDataInfos = new HashMap<>();
        for (CcCiInfo desginCI : desginCiInfos) {
            desginCodeAndDataInfos.put(desginCI.getCi().getCiCode(), desginCI);
        }

        for (CcCiInfo privateCI : privateCiInfos) {
            if (desginCodeAndDataInfos.containsKey(privateCI.getCi().getCiCode())) {
                // 对比 localVersion 与 publishVersion
                if (privateCI.getCi().getPublicVersion() < desginCodeAndDataInfos.get(privateCI.getCi().getCiCode()).getCi().getPublicVersion()) {
                    // 当前数据存在版本冲突
                    DiagramChangeData diagramChangeData = new DiagramChangeData(privateCI, desginCodeAndDataInfos.get(privateCI.getCi().getCiCode()), null, null);
                    versionChangeData.add(diagramChangeData);
                }
            }
        }
        return versionChangeData;
    }

    /**
     * 当前视图存在重名设计库的 CI 后端重新绑定code 并更新涉及到的所有视图数据
     *
     * @param diagramIds
     * @param names     当前名称含义为业务主键
     * @return
     */
    @Override
    public Boolean freshBindingEleByDEnergyId(List<String> diagramIds, List<String> names, Integer actionType) {
        SysUser currentUserInfo = SysUtil.getCurrentUserInfo();
        // 根据视图ID查询视图DTO
        List<ESDiagramDTO> esDiagramDTOS = this.queryDiagramInfoByIds(diagramIds);

        DiagramPrivateAndDesginData privateAndDesginDataByDEnergyId = this.getPrivateAndDesginDataByDEnergyId(esDiagramDTOS, currentUserInfo);
        // 获取私有库数据筛选
        Set<String> freshCodeList = new HashSet<>();
        Map<String, ESCIInfo> freshCodeMap = new HashMap<>();
        Map<String, String> freshOldAndNewCodes = new HashMap<>();

        if (actionType == Env.GENERAL_DIAGRAM_PUBLISH) {        // 发布刷新数据
            List<CcCiInfo> privateCiInfos = privateAndDesginDataByDEnergyId.getPrivateCiInfos();
            for (CcCiInfo privateCI : privateCiInfos) {
                if (names.contains(privateCI.getCi().getCiPrimaryKey())) {
                    ESCISearchBean esciSearchBean = new ESCISearchBean();
                    esciSearchBean.setClassIds(Collections.singletonList(privateCI.getCi().getClassId()));
                    esciSearchBean.setCiPrimaryKeys(Collections.singletonList(privateCI.getCi().getCiPrimaryKey()));
                    esciSearchBean.setPageNum(1);
                    esciSearchBean.setPageSize(10);
                    Page<ESCIInfo> esciInfoPage = ciSwitchSvc.searchESCIByBean(esciSearchBean, LibType.DESIGN);

                    freshCodeMap.put(privateCI.getCi().getCiCode(), esciInfoPage.getData().get(0));
                    freshOldAndNewCodes.put(privateCI.getCi().getCiCode(), esciInfoPage.getData().get(0).getCiCode());
                    freshCodeList.add(privateCI.getCi().getCiCode());
                    // 私有库数据code刷新
                    iamsESCIPrivateSvc.replaceCiCodeById(privateCI.getCi().getId(), esciInfoPage.getData().get(0).getCiCode());
                    // 私有库数据强制修改为设计库数据 发布版本修正为设计库版本 本地版本归0
                    privateCI.setAttrs(EamUtil.coverToAttrs(esciInfoPage.getData().get(0).getAttrs()));
                    privateCI.getCi().setCiCode(esciInfoPage.getData().get(0).getCiCode());
                    privateCI.getCi().setPublicVersion(esciInfoPage.getData().get(0).getPublicVersion());
                    privateCI.getCi().setLocalVersion(0L);
                    ciSwitchSvc.saveOrUpdateExtra(privateCI, LibType.PRIVATE);
                }
            }
        } else {        // 检出刷新数据
            List<CcCiInfo> desginCiInfos = privateAndDesginDataByDEnergyId.getDesginCiInfos();
            for (CcCiInfo desginCI : desginCiInfos) {
                if (names.contains(desginCI.getCi().getCiPrimaryKey())) {
                    ESCISearchBean esciSearchBean = new ESCISearchBean();
                    esciSearchBean.setClassIds(Collections.singletonList(desginCI.getCi().getClassId()));
                    esciSearchBean.setCiPrimaryKeys(Collections.singletonList(desginCI.getCi().getCiPrimaryKey()));
                    esciSearchBean.setOwnerCode(currentUserInfo.getLoginCode());
                    esciSearchBean.setPageNum(1);
                    esciSearchBean.setPageSize(10);
                    Page<ESCIInfo> esciInfoPage = ciSwitchSvc.searchESCIByBean(esciSearchBean, LibType.PRIVATE);
                    ESCIInfo esciInfo = esciInfoPage.getData().get(0);

                    freshCodeMap.put(esciInfo.getCiCode(), EamUtil.tranESCIInfo(desginCI));
                    freshOldAndNewCodes.put(esciInfo.getCiCode(), desginCI.getCi().getCiCode());
                    freshCodeList.add(esciInfo.getCiCode());
                    // 私有库数据code刷新
                    iamsESCIPrivateSvc.replaceCiCodeById(esciInfo.getId(), desginCI.getCi().getCiCode());

                    // 数据以设计库为准 ID使用私有库 更新私有库对应数据
                    desginCI.getCi().setId(esciInfo.getId());
                    desginCI.getCi().setLocalVersion(0L);
                    desginCI.getCi().setOwnerCode(currentUserInfo.getLoginCode());

                    ciSwitchSvc.saveOrUpdateExtra(desginCI, LibType.PRIVATE);
                }
            }
        }

        // 获取当前用户名下所有的视图  补充：当前用户名下的视图可能包含 业务建模 流程建模视图 需要添加目录文件逻辑
//        CVcDiagram cVcDiagram = new CVcDiagram();
//        cVcDiagram.setIsOpen(0);
//        cVcDiagram.setCreator(currentUserInfo.getLoginCode());

//        EamDiagramQuery eamDiagramQuery = new EamDiagramQuery();
//        eamDiagramQuery.setIsOpen(0);
//        eamDiagramQuery.setOwnerCodeEqual(currentUserInfo.getLoginCode());

        // 用户画图超过3000 选择scroll一次查出
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("isOpen", 0));
        boolQueryBuilder.must(QueryBuilders.termQuery("ownerCode.keyword", currentUserInfo.getLoginCode()));
        List<ESDiagram> listByCdt = esDiagramDao.getListByQueryScroll(boolQueryBuilder);

        // Page<ESSimpleDiagramDTO> curUserDiagramList = diagramApiClient.queryESDiagramInfoPage(currentUserInfo.getDomainId(), 1, 200, cVcDiagram, null);
        List<Long> diagramIdList = new ArrayList<>();
        for (ESDiagram esDiagram : listByCdt) {
            diagramIdList.add(esDiagram.getId());
        }

        // 根据私有库的code在node表中查询数据

        List<ESDiagramNode> freshNodeList = iamsEsDiagramNodeDao.getListByQuery(QueryBuilders.termsQuery("ciCode.keyword", freshCodeList));
        List<ESDiagramNode> updateData = new ArrayList<>();
        freshNodeList.forEach(e -> {
            if (diagramIdList.contains(e.getDiagramId().longValue())) {
                // e.setCiCode(freshCodeMap.get(e.getCiCode()));
                this.converNode(e, freshCodeMap);
                updateData.add(e);
            }
        });
        if (!CollectionUtils.isEmpty(updateData)) {
            iamsEsDiagramNodeDao.saveOrUpdateBatch(updateData);
        }

        // 关系Link 数据 刷新
        Set<String> freshCLinkList = new HashSet<>();
        Map<String, ESCIRltInfo> freshLinkCodeMap = new HashMap<>();
        List<ESCIRltInfo> privateRltInfos = privateAndDesginDataByDEnergyId.getPrivateRltInfos();
        for (ESCIRltInfo privateRlt : privateRltInfos) {
            if (freshCodeList.contains(privateRlt.getTargetCiCode()) || freshCodeList.contains(privateRlt.getSourceCiCode())) {
                // 记录当前关系 在设计库修改 并更新 link 表 逐条更新
                BindCiRltRequestDto bindCiRltRequestDto = new BindCiRltRequestDto();
                bindCiRltRequestDto.setAttrs(privateRlt.getAttrs());
                bindCiRltRequestDto.setRepetitionError(false);
                bindCiRltRequestDto.setOwnerCode(currentUserInfo.getLoginCode());
                bindCiRltRequestDto.setTargetCiId(privateRlt.getTargetCiId());
                bindCiRltRequestDto.setSourceCiId(privateRlt.getSourceCiId());
                bindCiRltRequestDto.setRltClassId(privateRlt.getClassId());
//                if (freshCodeMap.containsKey(privateRlt.getTargetCiCode())) {
//                    bindCiRltRequestDto.setTargetCiId(freshCodeMap.get(privateRlt.getTargetCiCode()).getId());
//                } else {
//                    bindCiRltRequestDto.setTargetCiId(privateRlt.getTargetCiId());
//                }
//                if (freshCodeMap.containsKey(privateRlt.getSourceCiCode())) {
//                    bindCiRltRequestDto.setSourceCiId(freshCodeMap.get(privateRlt.getSourceCiCode()).getId());
//                } else {
//                    bindCiRltRequestDto.setSourceCiId(privateRlt.getSourceCiId());
//                }
                Long aLong = ciRltSwitchSvc.bindCiRlt(bindCiRltRequestDto, LibType.PRIVATE);
                ESRltSearchBean esRltSearchBean = new ESRltSearchBean();
                CCcCiRlt cCcCiRlt = new CCcCiRlt();
                cCcCiRlt.setId(aLong);
                esRltSearchBean.setCdt(cCcCiRlt);
                Page<ESCIRltInfo> esciRltInfoPage = ciRltSwitchSvc.searchRlt(esRltSearchBean, LibType.PRIVATE);
                freshCLinkList.add(privateRlt.getUniqueCode());
                freshLinkCodeMap.put(privateRlt.getUniqueCode(), esciRltInfoPage.getData().get(0));
            }
        }

        List<ESDiagramLink> freshLinkList = iamsEsDiagramLinkDao.getListByQuery(QueryBuilders.termsQuery("uniqueCode.keyword", freshCLinkList));
        List<ESDiagramLink> updateLinks = new ArrayList<>();
        freshLinkList.forEach(e -> {
            if (diagramIds.contains(e.getDiagramId().longValue())) {
                // e.setCiCode(freshCodeMap.get(e.getCiCode()));
                this.converLink(e, freshLinkCodeMap);
                updateLinks.add(e);
            }
        });
        if (!CollectionUtils.isEmpty(updateLinks)) {
            iamsEsDiagramLinkDao.saveOrUpdateBatch(freshLinkList);
        }
        // 文件目录刷新 (补充逻辑)
        pushFacadeService.processCatalog(freshOldAndNewCodes, currentUserInfo.getLoginCode());
        return true;
    }

    @Override
    public Map<String, Boolean> getVersionChangeDiagramByDEnergyId(List<String> diagramIds) {
        // 查询视图详情
        List<ESDiagramDTO> esDiagramDTOS = this.queryDiagramInfoByIds(diagramIds);
        Map<String, Boolean> data = new HashMap<>();
        for (ESDiagramDTO esDiagramDTO : esDiagramDTOS) {
            if (BinaryUtils.isEmpty(esDiagramDTO.getDiagram().getReleaseDiagramId())) {
                // 当前视图未发布
                data.put(esDiagramDTO.getDiagram().getDEnergy(), false);
                continue;
            }
            if (BinaryUtils.isEmpty(esDiagramDTO.getDiagram().getReleaseVersion() == 0)) {
                throw new BinaryException("当前视图对比设计库发布视图未检核出任何修改");
            }
            // 查询当前视图发布的版本号
            Long releaseId = diagramApiClient.queryDiagramInfoByEnergy(esDiagramDTO.getDiagram().getReleaseDiagramId());
            ESDiagramDTO releaseDiagramInfo = diagramApiClient.queryESDiagramInfoById(releaseId, null, false);
            if (Integer.valueOf(esDiagramDTO.getDiagram().getReleaseVersion()) < Integer.valueOf(releaseDiagramInfo.getDiagram().getReleaseVersion())) {
                data.put(esDiagramDTO.getDiagram().getDEnergy(), true);     // 本地版本低于发布版本 需要检出
                continue;
            } else {
                data.put(esDiagramDTO.getDiagram().getDEnergy(), false);        // 本地版本等于发布版本 不需要检出
                continue;
            }
        }
        return data;
    }


    /**
     * node节点刷新
     *
     * @param e
     */
    private void converNode(ESDiagramNode e, Map<String, ESCIInfo> freshCodeMap) {
        final String code = freshCodeMap.get(e.getCiCode()).getCiCode();
        String nodeStr = e.getNodeJson();
        JSONObject nodeJson = JSON.parseObject(nodeStr);
        if (!BinaryUtils.isEmpty(nodeJson)) {
            if (!BinaryUtils.isEmpty(nodeJson.get("ciCode"))) {
                nodeJson.put("ciCode", code);
            }
        }
        e.setNodeJson(nodeJson.toJSONString());
        e.setCiCode(code);
    }

    /**
     * link节点刷新
     *
     * @param e
     */
    private void converLink(ESDiagramLink e, Map<String, ESCIRltInfo> freshCodeMap) {
        final String rltCode = freshCodeMap.get(e.getUniqueCode()).getUniqueCode();
        String linkStr = e.getLinkJson();
        JSONObject linkJson = JSON.parseObject(linkStr);
        if (!BinaryUtils.isEmpty(linkJson)) {
            if (!BinaryUtils.isEmpty(linkJson.get("rltCode"))) {
                linkJson.put("rltCode", rltCode);
            }
        }
        e.setLinkJson(linkJson.toJSONString());
        e.setUniqueCode(rltCode);
    }


    /**
     * ======用户通过数据 版本两次校验 查询视图上的变更数据 返回上层业务 根据具体业务处理数据====== （此时可以保证视图上存在设计库的+数据都关联完成）
     * 根据视图加密ID获取当前视图的变更集数据 ---CI
     *
     * @return
     */
    @Override
    public Map<String, List<DiagramChangeData>> getChangeCIDataByDEnergyId(String diagramId) {
        // 根据视图ID获取视图详情
        Long id = diagramApiClient.queryDiagramInfoByEnergy(diagramId);
        ESDiagramDTO esDiagramDTO = diagramApiClient.queryESDiagramInfoById(id, null, false);
        SysUser userInfoByOwnerCode = this.getUserInfoByOwnerCode(esDiagramDTO.getDiagram().getOwnerCode());
        DiagramPrivateAndDesginData privateAndDesginDataByDEnergyId = this.getPrivateAndDesginDataByDEnergyId(Collections.singletonList(esDiagramDTO), userInfoByOwnerCode);
        return this.getChangeCIDataByDEnergyIds(Collections.singletonList(esDiagramDTO), privateAndDesginDataByDEnergyId);
    }


    public Map<String, List<DiagramChangeData>> getChangeRltDataByDEnergyId(String dEnergyId) {
        // RLT 变更数据逻辑后期补充 暂时做覆盖处理

        return null;
    }

    /**
     * =======第一次校验======
     * 校验当前视图是否存在可以检出的对象
     *
     * @return
     */
    @Override
    public List<DiagramChangeData> isCheckOScanning(List<String> dEnergyIds) {
        /*
         *  视图发布前后台校验当前视图上数据是否可以正常发布
         *  特殊数据：CI主键唯一 视图上存在CI主键与设计库一致的数据 但数据code不一致 提示前端手动检核 更新数据
         *  需要检查检出返回对应数据的name 用户手动检出 不需要检出 返回null 进行下一步流程
         * */

        // 返回数据 data
        List<DiagramChangeData> nuptialData = new ArrayList<>();
        // 获取视图数据
        List<ESDiagramDTO> esDiagramDTOS = this.queryDiagramInfoByIds(dEnergyIds);
        SysUser userInfoByOwnerCode = this.getUserInfoByOwnerCode(esDiagramDTOS.get(0).getDiagram().getOwnerCode());
        return this.primaryKeyConflect(esDiagramDTOS, userInfoByOwnerCode);
    }

    public List<DiagramChangeData> primaryKeyConflect(List<ESDiagramDTO> esDiagramDTOS, SysUser userInfoByOwnerCode) {
        // 返回数据 data
        List<DiagramChangeData> nuptialData = new ArrayList<>();
        DiagramPrivateAndDesginData privateAndDesginDataByDEnergyId = this.getPrivateAndDesginDataByDEnergyId(esDiagramDTOS, userInfoByOwnerCode);
        List<CcCiInfo> privateCiInfos = privateAndDesginDataByDEnergyId.getPrivateCiInfos();
        List<CcCiInfo> desginCiInfos = privateAndDesginDataByDEnergyId.getDesginCiInfos();
        if (privateCiInfos.size() == desginCiInfos.size() || BinaryUtils.isEmpty(privateCiInfos)) {
            // 当前数据都绑定到设计库 一一对应
            return new ArrayList<>();
        }

        // CI code与data对应的map
        Map<String, CcCiInfo> privateCodeAndCiInfoMap = new HashMap<>();
        Map<String, CcCiInfo> desginCodeAndCiInfoMap = new HashMap<>();
        for (CcCiInfo privateCI : privateCiInfos) {
            privateCodeAndCiInfoMap.put(privateCI.getCi().getCiCode(), privateCI);
        }
        for (CcCiInfo desginCI : desginCiInfos) {
            desginCodeAndCiInfoMap.put(desginCI.getCi().getCiCode(), desginCI);
        }
        // 筛选出设计库不存在的数据 name
        Map<String, CcCiInfo> existPrivateNameAndDataList = new HashMap<>();
        for (CcCiInfo privateCI : privateCiInfos) {
            if (!desginCodeAndCiInfoMap.containsKey(privateCI.getCi().getCiCode())) {
                existPrivateNameAndDataList.put(privateCI.getCi().getCiPrimaryKey(), privateCI);
            }
        }
        //设计库根据名称查询是否存在同名要素
        List<ESCIInfo> nameEqualData = new ArrayList<>();

        if (MapUtils.isEmpty(existPrivateNameAndDataList)) {
            // 设计库导入导出可能存在异常数据 排除异常数据影响
            return nuptialData;
        }
        List<String> ciPrimaryKeys = new ArrayList<>();
        List<Long> classIds = new ArrayList<>();
        existPrivateNameAndDataList.values().forEach(e -> {
            ciPrimaryKeys.add(e.getCi().getCiPrimaryKey());
            classIds.add(e.getCi().getClassId());
        });
        ESCISearchBean esciSearchBean = new ESCISearchBean();
        esciSearchBean.setCiPrimaryKeys(ciPrimaryKeys);
        esciSearchBean.setClassIds(classIds);
        esciSearchBean.setPageNum(1);
        esciSearchBean.setPageSize(500);
        Page<ESCIInfo> esciInfoPage = ciSwitchSvc.searchESCIByBean(esciSearchBean, LibType.DESIGN);
        nameEqualData.addAll(esciInfoPage.getData());
        if (CollectionUtils.isEmpty(nameEqualData)) {
            // 设计库无重名要素 不需要检出
            return new ArrayList<>();
        }

        List<String> ciCodes = nameEqualData.stream().map(ESCIInfo::getCiCode).collect(Collectors.toList());
        CCcCi cdt = new CCcCi();
        cdt.setCiCodes(ciCodes.toArray(new String[ciCodes.size()]));

        List<CcCiInfo> ccCiInfos = ciSwitchSvc.queryCiInfoList(1L, cdt, null, false, true, LibType.DESIGN);

        for (CcCiInfo esciInfo : ccCiInfos) {
            DiagramChangeData diagramChangeData = new DiagramChangeData(existPrivateNameAndDataList.get(esciInfo.getCi().getCiPrimaryKey()), esciInfo, null, null);
            nuptialData.add(diagramChangeData);
        }
        return nuptialData;
    }

    @Override
    public Map<String, ESDiagramDTO> queryDiagramInfoByIdAndVersion(Map<String, Integer> data) {
        /*
        *  根据传递的视图ID(私有库ID) 和 视图releaseVersion(设计库) 查询视图信息
        *
        * */

        Map<String, ESDiagramDTO> result = new HashMap<>();     // 返回值
        BoolQueryBuilder query = new BoolQueryBuilder();
        query.must(QueryBuilders.termsQuery("dEnergy.keyword", data.keySet()));
        List<ESDiagram> privateDiagramInfos = esDiagramDao.getListByQuery(query);

        Map<String, String> privateAndDesginIdMap = new HashMap<>();
        privateDiagramInfos.forEach(e -> {
            // 正常数据在发布之后releaseDiagramId都应该有值
            if (!BinaryUtils.isEmpty(e.getReleaseDiagramId())) {
                privateAndDesginIdMap.put(e.getDEnergy(), e.getReleaseDiagramId());
            }
        });

        List<Long> versionId = new ArrayList<>();   // 对应的发布版本id

        // 循环查询发布视图对应的版本信息
        for (String privateDiagramId : privateAndDesginIdMap.keySet()) {
            BoolQueryBuilder queryDesgin = new BoolQueryBuilder();
            queryDesgin.must(QueryBuilders.termQuery("releaseDiagramId.keyword", privateAndDesginIdMap.get(privateDiagramId)));
            queryDesgin.must(QueryBuilders.termQuery("isOpen", 1));     // 设计库视图
            queryDesgin.must(QueryBuilders.termQuery("releaseVersion", data.get(privateDiagramId)));        // 对应的版本号
            List<ESDiagram> desginDiagramInfos = esDiagramDao.getListByQuery(queryDesgin);
            if (CollectionUtils.isEmpty(desginDiagramInfos)) {
                throw new BinaryException("视图ID：" + privateDiagramId + "不存在版本号为" + data.get(privateDiagramId) + "的数据，请联系管理员排查!");
            }
            versionId.add(desginDiagramInfos.get(0).getId());
        }

        // 根据ID查询详情返回
        List<ESDiagramDTO> esDiagramDTOS = diagramApiClient.queryDiagramInfoByIds(versionId.toArray(new Long[versionId.size()]), "CJ_D_HISTORY", false, Boolean.FALSE);
        // 映射结果返回
        for (String privateDiagramId : privateAndDesginIdMap.keySet()) {
            for (ESDiagramDTO esDiagramDTO : esDiagramDTOS) {
                if (privateAndDesginIdMap.get(privateDiagramId).equals(esDiagramDTO.getDiagram().getReleaseDiagramId())) {
                    result.put(privateDiagramId, esDiagramDTO);
                }
            }
        }
        return result;
    }

    @Override
    public Map<Integer, Object> checkDiagramConflictByDIds(List<String> diagramIds) {
        /*
        *  通用视图发布前校验：（适用于除流程建模以外所有视图发布流程）
        *  校验步骤：
        *      1.视图内CI的业务主键冲突情况
        *      2.关联制品的视图制品数量约束情况
        *      3.视图内CI必填项
        *      4.视图数据的版本
        *      5.视图内CI的版本
        *  接口支持批量处理，支持多用户的数据同时校验
        *
        * */
        Map<Integer, Object> result = new HashMap<>();

        // 根据ownerCode 先将整体数据做区分 K - 用户 V - 对应的视图集合
        List<ESDiagramDTO> esDiagramDTOS = this.queryDiagramInfoByIds(diagramIds);
        esDiagramDTOS.forEach(e -> {
            if (BinaryUtils.isEmpty(e.getDiagram().getViewType())) {
                // 未关联制品的数据暂时将viewType设置为0，方便后续校验分组
                e.getDiagram().setViewType("0");
            }
        });
        Map<String, List<ESDiagramDTO>> userData = esDiagramDTOS.stream().collect(Collectors.groupingBy(e -> e.getDiagram().getOwnerCode()));       // 用户 和 用户对应的视图数据
        Map<String, DiagramPrivateAndDesginData> privateAndDesginDataByUserCode = new HashMap<>();      // 根据用户信息 区分 私有库/设计库 数据

        for (String userId : userData.keySet()) {
            DiagramPrivateAndDesginData privateAndDesginDataByDEnergyId = this.getPrivateAndDesginDataByDEnergyId(userData.get(userId), getUserInfoByOwnerCode(userId));
            privateAndDesginDataByUserCode.put(userId, privateAndDesginDataByDEnergyId);
        }

        // 根据视图加密ID查询视图node节点
        Long[] ids = diagramApiClient.queryDiagramInfoBydEnergy(diagramIds.toArray(new String[diagramIds.size()]));
        ESDiagramNodeQueryBean nodeQueryBean = new ESDiagramNodeQueryBean();
        nodeQueryBean.setDiagramIds(ids);
        List<ESDiagramNode> nodeList = iamsEsDiagramNodeDao.getListByCdt(nodeQueryBean);
        Map<String, List<ESDiagramNode>> idAndNodeInfo = nodeList.stream().collect(Collectors.groupingBy(e -> e.getdEnergy()));     // 根据视图ID去做分离node数据

        /*
        *  一.校验业务主键冲突情况 因为存在多用户数据的情况 后端暂时限制处理数据的规定：
        *   1.当前用户的视图可以直接处理
        *   2.非当前用户数据提示交给对应创建者处理
        *
        *   将视图数据先以用户做维度进行分组，查询出每个用户下需要发布的CI数据
        *   根据[业务主键],[ciCode]为条件，对比当前视图上的CI数据，进行冲突校验
        * */

        Map<String, List<DiagramChangeData>> primaryKeyConflect = this.checkPrimaryKeyConflict(userData, privateAndDesginDataByUserCode);
        List<DiagramChangeData> conflectData = new ArrayList<>();
        for (String userCode : primaryKeyConflect.keySet()) {
            conflectData.addAll(primaryKeyConflect.get(userCode));
        }
        if (!CollectionUtils.isEmpty(conflectData)) {
            // 主键校验未通过 与前端约定好返回方式 展示提示信息
            result.put(PRIMARY_KEY_CHECK, coverPrimaryConflentData(primaryKeyConflect, idAndNodeInfo, userData));
            return result;
        }

        /*
        *  二.校验视图关联制品数量限制，多用户可以并行处理 将所有视图使用到的制品统一查询处理
        *   当前维度不需要考虑视图用户 每一个制品下的所有视图 K -> 制品ID V -> 视图信息集合
        *
        *   将视图先以关联制品的维度进行分组 之后开始进行校验
        *   获取制品的信息，提取出每个制品中的约束条件
        *   获取每张视图中的 {被当前关联制品约束的分类} 的 {CI的数量}
        *   拿到上面数据进行循环遍历，获得校验信息
        * */

        Map<Long, List<ESDiagramDTO>> productNumData = esDiagramDTOS.stream().collect(Collectors.groupingBy(e -> Long.valueOf(e.getDiagram().getViewType())));       // 制品 和 制品的视图数据
        Map<String, List<String>> productCheckData = this.checkCategoryEleNum(productNumData, idAndNodeInfo);       // 返回信息为每张视图对应的约束校验集合
        List<String> allCheckData = new ArrayList<>();     // 所有视图的数量校验结果
        for (String checkData : productCheckData.keySet()) {
            allCheckData.addAll(productCheckData.get(checkData));
        }
        if (!CollectionUtils.isEmpty(allCheckData)) {
            // 制品个数批量校验未通过
            result.put(PRODUCT_NUM_CHECK, productCheckData);
            return result;
        }

        /*
        *  三.校验视图内CI必填项
        *
        *   将数据以用户为维度区分
        *   查询出用户名下的CI数据 校验每个CI的必填项信息
        *   查询出每张视图图内对应的node
        *   将上属数据进行重组 获取返回值
        *
        * */
        Map<String, Map<String, String>> requiredFieldCheckData = this.checkRequiredFieldByIds(userData, privateAndDesginDataByUserCode, idAndNodeInfo);
        Map<String, String> allRequiredFieldCheckData = new HashMap<>();
        for (String errMsg : requiredFieldCheckData.keySet()) {
            allRequiredFieldCheckData.putAll(requiredFieldCheckData.get(errMsg));
        }
        if (!MapUtils.isEmpty(allRequiredFieldCheckData)) {
            // CI必填项批量校验未通过
            result.put(REQUIRED_FIELD_CHECK, requiredFieldCheckData);
            return result;
        }

        /*
        *  四.校验视图数据版本 (可以以视图为维度进行校验)
        *
        * */
        Map<String, Boolean> diagramVersionCheckData = this.checkDiagramVersionByIds(esDiagramDTOS);
        List<Boolean> allDiagramVersionData = new ArrayList<>();
        for (String diagramId : diagramVersionCheckData.keySet()) {
            allDiagramVersionData.add(diagramVersionCheckData.get(diagramId));
        }
        if (allDiagramVersionData.contains(true)) {
            // 视图版本批量校验未通过
            result.put(DIAGRAM_VERSION_CHECK, diagramVersionCheckData);
            return result;
        }

        /*
        *  五.校验视图CI版本 (需要以用户为维度进行数据校验)
        *
        * */
        Map<String, List<DiagramChangeData>> userConflectData = this.checkCIVersionByIds(userData, privateAndDesginDataByUserCode);     // 获取用户名下的冲突数据
        Map<String, Boolean> ciVersionCheckData = this.transDiagramConflectData(userConflectData, userData, idAndNodeInfo);
        List<Boolean> allCIVersionData = new ArrayList<>();
        for (String diagramId : ciVersionCheckData.keySet()) {
            allCIVersionData.add(ciVersionCheckData.get(diagramId));
        }
        if (allCIVersionData.contains(true)) {
            // 视图版本批量校验未通过
            result.put(CI_VERSION_CHECK, ciVersionCheckData);
            return result;
        }
        return result;
    }

    @Override
    public Boolean freshConflectData(List<String> ciPrimaryKeys, String ownerCode) {
        // 直接根据业务主键和用户信息获取 私有库/ 设计库对应的信息
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termsQuery("ciPrimaryKey.keyword", ciPrimaryKeys));
        List<ESCIInfo> desginCIInfos = iamsESCIDesignSvc.getListByQuery(boolQueryBuilder);
        boolQueryBuilder.must(QueryBuilders.termQuery("ownerCode.keyword",ownerCode));
        List<ESCIInfo> privateCIInfos = iamsESCIPrivateSvc.getListByQuery(boolQueryBuilder);

        // 设计库数据以业务主键字段生成map
        Map<String, ESCIInfo> keyPrimaryMap = desginCIInfos.stream().collect(Collectors.toMap(e -> e.getCiPrimaryKey(), e -> e, (k1, k2) -> k2));

        // 获取私有库数据筛选
        Set<String> freshCodeList = new HashSet<>();
        Map<String, ESCIInfo> freshCodeMap = new HashMap<>();
        Map<String, String> freshOldAndNewCodes = new HashMap<>();
        List<ESCIInfo> updatePrivateCIData = new ArrayList<>();
        List<Long> updateClassIds = new ArrayList<>();

        for (ESCIInfo privateCI : privateCIInfos) {
            if (ciPrimaryKeys.contains(privateCI.getCiPrimaryKey())) {
                ESCIInfo desginCIInfo = keyPrimaryMap.get(privateCI.getCiPrimaryKey());
                freshCodeMap.put(privateCI.getCiCode(), desginCIInfo);
                freshOldAndNewCodes.put(privateCI.getCiCode(), desginCIInfo.getCiCode());
                freshCodeList.add(privateCI.getCiCode());
                // 私有库数据code刷新
                iamsESCIPrivateSvc.replaceCiCodeById(privateCI.getId(), desginCIInfo.getCiCode());
                // 私有库数据强制修改为设计库数据 发布版本修正为设计库版本 本地版本归0
                privateCI.setAttrs(desginCIInfo.getAttrs());
                privateCI.setCiCode(desginCIInfo.getCiCode());
                privateCI.setPublicVersion(desginCIInfo.getPublicVersion());
                privateCI.setLocalVersion(0L);
                updatePrivateCIData.add(privateCI);
                updateClassIds.add(privateCI.getClassId());

            }
        }
        // 批量更新私有库的冲突数据
        ciSwitchSvc.saveOrUpdateBatchCI(updatePrivateCIData, updateClassIds, ownerCode, ownerCode, LibType.PRIVATE);

        // 获取当前用户名下所有的视图  补充：当前用户名下的视图可能包含 业务建模 流程建模视图 需要添加目录文件逻辑
        CVcDiagram cVcDiagram = new CVcDiagram();
        cVcDiagram.setIsOpen(0);
        cVcDiagram.setCreator(ownerCode);
        Page<ESSimpleDiagramDTO> curUserDiagramList = diagramApiClient.queryESDiagramInfoPage(1L, 1, 500, cVcDiagram, null);
        List<Long> diagramIds = new ArrayList<>();
        for (ESSimpleDiagramDTO esSimpleDiagramDTO : curUserDiagramList.getData()) {
            diagramIds.add(esSimpleDiagramDTO.getDiagram().getId());
        }

        // 根据私有库的code在node表中查询数据

        List<ESDiagramNode> freshNodeList = iamsEsDiagramNodeDao.getListByQuery(QueryBuilders.termsQuery("ciCode.keyword", freshCodeList));
        List<ESDiagramNode> updateData = new ArrayList<>();
        freshNodeList.forEach(e -> {
            if (diagramIds.contains(e.getDiagramId().longValue())) {
                // e.setCiCode(freshCodeMap.get(e.getCiCode()));
                this.converNode(e, freshCodeMap);
                updateData.add(e);
            }
        });
        if (!CollectionUtils.isEmpty(updateData)) {
            iamsEsDiagramNodeDao.saveOrUpdateBatch(updateData);
        }

        // 关系Link 数据 刷新
        Set<String> freshCLinkList = new HashSet<>();
        Map<String, ESCIRltInfo> freshLinkCodeMap = new HashMap<>();

        // 查询用户私有库关系数据
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        // 源端目标端条件满足其一
        BoolQueryBuilder ciBoolQuery = QueryBuilders.boolQuery();
        ciBoolQuery.should(QueryBuilders.termsQuery("sourceCiCode.keyword", freshCodeList));
        ciBoolQuery.should(QueryBuilders.termsQuery("targetCiCode.keyword", freshCodeList));

        boolQuery.must(ciBoolQuery);
        boolQuery.must(QueryBuilders.termQuery("ownerCode.keyword", ownerCode));
        List<ESCIRltInfo> privateRltInfos = iamsESCIRltPirvateSvc.getListByQuery(boolQuery);
        for (ESCIRltInfo privateRlt : privateRltInfos) {
            if (freshCodeList.contains(privateRlt.getTargetCiCode()) || freshCodeList.contains(privateRlt.getSourceCiCode())) {
                // 记录当前关系 在设计库修改 并更新 link 表 逐条更新
                BindCiRltRequestDto bindCiRltRequestDto = new BindCiRltRequestDto();
                bindCiRltRequestDto.setAttrs(privateRlt.getAttrs());
                bindCiRltRequestDto.setRepetitionError(false);
                bindCiRltRequestDto.setOwnerCode(ownerCode);
                bindCiRltRequestDto.setTargetCiId(privateRlt.getTargetCiId());
                bindCiRltRequestDto.setSourceCiId(privateRlt.getSourceCiId());
                bindCiRltRequestDto.setRltClassId(privateRlt.getClassId());

                Long aLong = ciRltSwitchSvc.bindCiRlt(bindCiRltRequestDto, LibType.PRIVATE);
                ESRltSearchBean esRltSearchBean = new ESRltSearchBean();
                CCcCiRlt cCcCiRlt = new CCcCiRlt();
                cCcCiRlt.setId(aLong);
                esRltSearchBean.setCdt(cCcCiRlt);
                Page<ESCIRltInfo> esciRltInfoPage = ciRltSwitchSvc.searchRlt(esRltSearchBean, LibType.PRIVATE);
                freshCLinkList.add(privateRlt.getUniqueCode());
                freshLinkCodeMap.put(privateRlt.getUniqueCode(), esciRltInfoPage.getData().get(0));
            }
        }

        List<ESDiagramLink> freshLinkList = iamsEsDiagramLinkDao.getListByQuery(QueryBuilders.termsQuery("uniqueCode.keyword", freshCLinkList));
        List<ESDiagramLink> updateLinks = new ArrayList<>();
        freshLinkList.forEach(e -> {
            if (diagramIds.contains(e.getDiagramId().longValue())) {
                // e.setCiCode(freshCodeMap.get(e.getCiCode()));
                this.converLink(e, freshLinkCodeMap);
                updateLinks.add(e);
            }
        });
        if (!CollectionUtils.isEmpty(updateLinks)) {
            iamsEsDiagramLinkDao.saveOrUpdateBatch(freshLinkList);
        }
        // 文件目录刷新 (补充逻辑)
        pushFacadeService.processCatalog(freshOldAndNewCodes, ownerCode);
        return true;
    }

    @Override
    public List<CcCiInfo> getHistroyCIInfoByDiagramId(String diagramId, String sheetId) {
        // 获取视图发布信息
        List<ESDiagram> listByQuery = esDiagramDao.getListByQuery(QueryBuilders.termQuery("dEnergy.keyword", diagramId));
        if (CollectionUtils.isEmpty(listByQuery)) {
            // 视图信息异常时直接返回空数据给前端 防止页面弹窗
            return new ArrayList<>();
        }
        // 根据视图的eid 获取对应的 CI / RLT 数据
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("dEnergy.keyword", diagramId));
        if (!BinaryUtils.isEmpty(sheetId)) {
            boolQueryBuilder.must(QueryBuilders.termQuery("sheetId.keyword", sheetId));
        }
        List<ESDiagramNode> nodeList = iamsEsDiagramNodeDao.getListByQuery(boolQueryBuilder);

        Map<String, ESDiagramNode> nodeCodeAndDataMap = new HashMap<>();
        List<String> noVersionCIList = new ArrayList<>();
        List<String> privateCiCodeList = new ArrayList<>();     // 用于私有库查询
        nodeList.forEach(node -> {
            if (BinaryUtils.isEmpty(node.getCiCode())) {
                log.info("####### 当前节点为图形 未绑定数据 nodeId = " + node.getId() + " #######");
            } else {
                if (BinaryUtils.isEmpty(node.getVersion())) {
                    noVersionCIList.add(node.getCiCode());
                } else {
                    nodeCodeAndDataMap.put(node.getCiCode(), node);
                }
                privateCiCodeList.add(node.getCiCode());
            }
        });

        List<CcCiInfo> data = new ArrayList<>();
        ESDiagram diagram = listByQuery.get(0);
        // 此处需要兼容本地预览模式 查询私有库数据
        if (diagram.getIsOpen() == 0) {
            if (CollectionUtils.isEmpty(privateCiCodeList)) {
                return new ArrayList<>();
            }
            // 查询私有库数据
            CCcCi cdt = new CCcCi();
            cdt.setCiCodes(privateCiCodeList.toArray(new String[privateCiCodeList.size()]));
            cdt.setOwnerCodeEqual(SysUtil.getCurrentUserInfo().getLoginCode());
            //流程中的视图放开查看私有库节点数据
            if (diagram.getFlowStatus() != null && diagram.getFlowStatus() == 2) {
                cdt.setOwnerCodeEqual(diagram.getOwnerCode());
            }
            List<CcCiInfo> noVersionCIInfos = iamsESCIPrivateSvc.queryCiInfoList(cdt, null, false, true);
            data.addAll(noVersionCIInfos);
        } else {

            // 正常的节点信息在历史表中查询对应的数据
            if (MapUtils.isEmpty(nodeCodeAndDataMap)) {
                // todo 节点全是历史数据  感觉好像需要处理什么。。。
            } else {
                // 根据 version 和 ciCode 查询CI数据
                BoolQueryBuilder ciHistoryQuery = QueryBuilders.boolQuery();
                // 循环放入查询条件
                for (String nodeCode : nodeCodeAndDataMap.keySet()) {
                    // verison字段历史数据没有绑定 需要兼容 如果不存在版本 暂时查询历史库当前资产的最新版本
                    BoolQueryBuilder oneQuery = QueryBuilders.boolQuery();
                    /*
                    * 这个version字段即使绑定到节点上 也存在有的历史数据在设计库历史表中查不到数据 会导致查询的数据缺失 这个要排查
                    * 分类数据在导入导出的删除再导入的时候 会将历史表中的CI ciCode关联的列表数据全部删除 再次导入的时候ciCode不变 但是历史版本会重新开始计算
                    * 这里后台做一下兼容 根据ciCode和版本号查询不到历史表数据就返回设计库当前数据
                    *
                    * 历史表数据的生成规则不支持上述操作之后的查询 所以遇到上述操作的视图 再去查询历史数据就没有意义
                    * */
                    oneQuery.must(QueryBuilders.termQuery("version", nodeCodeAndDataMap.get(nodeCode).getVersion()));
                    oneQuery.must(QueryBuilders.termQuery("ciCode.keyword", nodeCode));
                    ciHistoryQuery.should(oneQuery);
                }
                List<ESCIHistoryInfo> historyCIList = iamsESCIHistoryDesignSvc.getListByQuery(ciHistoryQuery);

                if (historyCIList.size() != nodeCodeAndDataMap.keySet().size()) {
                    // 存在上述的版本号查询异常情况 在此进行补充查询 查询对象为设计库当前数据 也就是直接把当前数据算作无版本号数据处理
                    log.info("############ 节点数据根据 version 和 ciCode 在历史库查询存在异常，部分数据需要进行二次查询");
                    List<String> historyCode = historyCIList.stream().map(ESCIHistoryInfo::getCiCode).collect(Collectors.toList());
                    for (String code : nodeCodeAndDataMap.keySet()) {
                        if (!historyCode.contains(code)) {
                            noVersionCIList.add(code);
                            log.info("############ 节点CI数据ciCode：【{}】存在version：【{}】，但是历史库无法查询。", code, nodeCodeAndDataMap.get(code).getVersion());
                        }
                    }
                }

                // 查询分类信息
                Set<Long> classIds = new HashSet<>();
                historyCIList.forEach(classInfo -> {
                    classIds.add(classInfo.getClassId());
                });
                CCcCiClass cdt = new CCcCiClass();
                cdt.setIds(classIds.toArray(new Long[classIds.size()]));
                List<CcCiClassInfo> classInfoList = esciClassSvc.queryCiClassInfoList(cdt, null, false);
                // List<ESCIClassInfo> classInfoList = esciClassSvc.getListByQuery(QueryBuilders.termsQuery("id", classIds));
                Map<Long, CcCiClassInfo> classIdAndDataMap = new HashMap<Long, CcCiClassInfo>() {{
                    classInfoList.forEach(info -> {
                        put(info.getCiClass().getId(), info);
                    });
                }};

                // 捏合数据 这里这么搞是因为有一部分历史数据在设计库创建成功但是在历史库没找到 只能去捏。。
                List<CcCiInfo> ccCiInfos = this.coverCIHisInfoToCIInfo(historyCIList, classIdAndDataMap);
                data.addAll(ccCiInfos);
            }

            // 在设计库查询出节点 无版本号的数据 以及 存在版本号但查询不到 的信息 兼容历史数据的信息
            if (!CollectionUtils.isEmpty(noVersionCIList)) {
                CCcCi cdt = new CCcCi();
                cdt.setCiCodes(noVersionCIList.toArray(new String[noVersionCIList.size()]));
                List<CcCiInfo> noVersionCIInfos = iamsESCIDesignSvc.queryCiInfoList(cdt, null, false, true);
                data.addAll(noVersionCIInfos);
            }

        }

        return data;
    }

    @Override
    public List<CcCiInfo> getHistroyCIInfoByDiagramIdWithoutCiClass(String diagramId, String sheetId) {
        // 获取视图发布信息
        List<ESDiagram> listByQuery = esDiagramDao.getListByQuery(QueryBuilders.termQuery("dEnergy.keyword", diagramId));
        if (CollectionUtils.isEmpty(listByQuery)) {
            // 视图信息异常时直接返回空数据给前端 防止页面弹窗
            return new ArrayList<>();
        }
        // 根据视图的eid 获取对应的 CI / RLT 数据
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("dEnergy.keyword", diagramId));
        if (!BinaryUtils.isEmpty(sheetId)) {
            boolQueryBuilder.must(QueryBuilders.termQuery("sheetId.keyword", sheetId));
        }
        List<ESDiagramNode> nodeList = iamsEsDiagramNodeDao.getListByQuery(boolQueryBuilder);

        Map<String, ESDiagramNode> nodeCodeAndDataMap = new HashMap<>();
        List<String> noVersionCIList = new ArrayList<>();
        List<String> privateCiCodeList = new ArrayList<>();     // 用于私有库查询
        nodeList.forEach(node -> {
            if (BinaryUtils.isEmpty(node.getCiCode())) {
                log.info("####### 当前节点为图形 未绑定数据 nodeId = " + node.getId() + " #######");
            } else {
                if (BinaryUtils.isEmpty(node.getVersion())) {
                    noVersionCIList.add(node.getCiCode());
                } else {
                    nodeCodeAndDataMap.put(node.getCiCode(), node);
                }
                privateCiCodeList.add(node.getCiCode());
            }
        });

        List<CcCiInfo> data = new ArrayList<>();
        // 此处需要兼容本地预览模式 查询私有库数据
        ESDiagram diagram = listByQuery.get(0);
        if (diagram.getIsOpen() == 0) {
            if (CollectionUtils.isEmpty(privateCiCodeList)) {
                return new ArrayList<>();
            }
            // 查询私有库数据
            CCcCi cdt = new CCcCi();
            cdt.setCiCodes(privateCiCodeList.toArray(new String[privateCiCodeList.size()]));
            cdt.setOwnerCodeEqual(SysUtil.getCurrentUserInfo().getLoginCode());
            //流程中的视图放开查看私有库节点数据 驳回代办临时兼容一下
            if (diagram.getFlowStatus() != null && diagram.getFlowStatus() != 0) {
                cdt.setOwnerCodeEqual(diagram.getOwnerCode());
            }
            List<CcCiInfo> noVersionCIInfos = iamsESCIPrivateSvc.queryCiInfoList(cdt, null, false, false);
            data.addAll(noVersionCIInfos);
            return data;
        }
        // 正常的节点信息在历史表中查询对应的数据
        if (MapUtils.isEmpty(nodeCodeAndDataMap)) {
            // todo 节点全是历史数据  感觉好像需要处理什么。。。
        } else {
            // 根据 version 和 ciCode 查询CI数据
            BoolQueryBuilder ciHistoryQuery = QueryBuilders.boolQuery();
            // 循环放入查询条件
            for (String nodeCode : nodeCodeAndDataMap.keySet()) {
                // verison字段历史数据没有绑定 需要兼容 如果不存在版本 暂时查询历史库当前资产的最新版本
                BoolQueryBuilder oneQuery = QueryBuilders.boolQuery();
                /*
                 * 这个version字段即使绑定到节点上 也存在有的历史数据在设计库历史表中查不到数据 会导致查询的数据缺失 这个要排查
                 * 分类数据在导入导出的删除再导入的时候 会将历史表中的CI ciCode关联的列表数据全部删除 再次导入的时候ciCode不变 但是历史版本会重新开始计算
                 * 这里后台做一下兼容 根据ciCode和版本号查询不到历史表数据就返回设计库当前数据
                 *
                 * 历史表数据的生成规则不支持上述操作之后的查询 所以遇到上述操作的视图 再去查询历史数据就没有意义
                 * */
                oneQuery.must(QueryBuilders.termQuery("version", nodeCodeAndDataMap.get(nodeCode).getVersion()));
                oneQuery.must(QueryBuilders.termQuery("ciCode.keyword", nodeCode));
                ciHistoryQuery.should(oneQuery);
            }
            List<ESCIHistoryInfo> historyCIList = iamsESCIHistoryDesignSvc.getListByQuery(ciHistoryQuery);

            if (historyCIList.size() != nodeCodeAndDataMap.keySet().size()) {
                // 存在上述的版本号查询异常情况 在此进行补充查询 查询对象为设计库当前数据 也就是直接把当前数据算作无版本号数据处理
                log.info("############ 节点数据根据 version 和 ciCode 在历史库查询存在异常，部分数据需要进行二次查询");
                List<String> historyCode = historyCIList.stream().map(ESCIHistoryInfo::getCiCode).collect(Collectors.toList());
                for (String code : nodeCodeAndDataMap.keySet()) {
                    if (!historyCode.contains(code)) {
                        noVersionCIList.add(code);
                        log.info("############ 节点CI数据ciCode：【{}】存在version：【{}】，但是历史库无法查询。", code, nodeCodeAndDataMap.get(code).getVersion());
                    }
                }
            }

            // 查询分类信息
            Set<Long> classIds = historyCIList.stream().map(ESCIHistoryInfo::getClassId).collect(Collectors.toSet());
            CCcCiClass cdt = new CCcCiClass();
            cdt.setIds(classIds.toArray(new Long[classIds.size()]));
            List<CcCiClassInfo> classInfoList = esciClassSvc.queryCiClassInfoList(cdt, null, false);
            // 捏合数据 这里这么搞是因为有一部分历史数据在设计库创建成功但是在历史库没找到 只能去捏。。
            List<CcCiInfo> ccCiInfos = this.coverCIHisInfoToCIInfoNew(historyCIList, classInfoList, "COMMON");
            data.addAll(ccCiInfos);
        }

        // 在设计库查询出节点 无版本号的数据 以及 存在版本号但查询不到 的信息 兼容历史数据的信息
        if (!CollectionUtils.isEmpty(noVersionCIList)) {
            CCcCi cdt = new CCcCi();
            cdt.setCiCodes(noVersionCIList.toArray(new String[noVersionCIList.size()]));
            List<CcCiInfo> noVersionCIInfos = iamsESCIDesignSvc.queryCiInfoList(cdt, null, false, false);
            data.addAll(noVersionCIInfos);
        }
        return data;
    }

    /**
     *  将CI的esHistroyInfo格式的数据转换成esInfo格式
     * @param esciHistoryInfos
     * @param classInfoList
     * @return
     */
    @Override
    public List<CcCiInfo> coverCIHisInfoToCIInfoNew(List<ESCIHistoryInfo> esciHistoryInfos, List<CcCiClassInfo> classInfoList, String type) {
        if (CollectionUtils.isEmpty(esciHistoryInfos) || CollectionUtils.isEmpty(classInfoList)) {
            return new ArrayList<>();
        }
        //取映射表查CI属性变更
        Set<Long> defIds = new HashSet<>();
        Map<Long, CcCiClassInfo> classInfoMap = new HashMap<>();
        classInfoList.forEach(classInfo -> {
            defIds.addAll(classInfo.getAttrDefs().stream().map(CcCiAttrDef::getId).collect(Collectors.toSet()));
            classInfoMap.put(classInfo.getCiClass().getId(), classInfo);
        });
        List<ESCIAttrTransConfig> attrTransConfigs = attrConfigSvc.getListByQuery(QueryBuilders.termsQuery("defId", defIds));
        Map<Long, List<ESCIAttrTransConfig>> groupByCiClassIdAttrTransConfMap = new ConcurrentHashMap<>();
        if (!CollectionUtils.isEmpty(attrTransConfigs)) {
            groupByCiClassIdAttrTransConfMap = attrTransConfigs.stream().collect(Collectors.groupingBy(ESCIAttrTransConfig::getClassId));
        }

        List<CcCiInfo> ccCiInfos = new ArrayList<>();
        for (ESCIHistoryInfo esCI : esciHistoryInfos) {
            String jsonStr = JSON.toJSONString(esCI, SerializerFeature.WriteMapNullValue).replaceAll("null", "''");
            JSONObject json = JSON.parseObject(jsonStr);
            CcCiInfo ciInfo = JSON.toJavaObject(json, CcCiInfo.class);
            CcCi ci = JSON.toJavaObject(json, CcCi.class);
            ciInfo.setCi(ci);
            if (groupByCiClassIdAttrTransConfMap.containsKey(esCI.getClassId())) {
                Map<String, String> attrs = ciInfo.getAttrs();
                List<ESCIAttrTransConfig> attrTransConfs = groupByCiClassIdAttrTransConfMap.get(esCI.getClassId());
                for (ESCIAttrTransConfig attrTransConf : attrTransConfs) {
                    if (attrTransConf.getUpType() == 1) {
                        // 修改名称
                        if (!attrs.containsKey(attrTransConf.getSourceAttrName().toUpperCase())) {
                            continue;
                        }
                        //添加映射属性
                        attrs.put(attrTransConf.getShowName().toUpperCase(), ciInfo.getAttrs().get(attrTransConf.getSourceAttrName().toUpperCase()));
                        //删除原属性
                        attrs.remove(attrTransConf.getSourceAttrName().toUpperCase());
                    } else {
                        // 修改字段类型
                        if (!attrs.containsKey(attrTransConf.getTargetAttrName())) {
                            continue;
                        }
                        //添加映射属性
                        attrs.put(attrTransConf.getShowName(), ciInfo.getAttrs().get(attrTransConf.getTargetAttrName()));
                        //删除原属性
                        attrs.remove(attrTransConf.getTargetAttrName());
                    }
                }
                ciInfo.setAttrs(attrs);
            }
            if (type.equals("SNAPSHOT")) {
                // 查询快照/历史版本数据返回字段定义信息
                Long classId = esCI.getClassId();
                if (!BinaryUtils.isEmpty(classId)) {
                    ciInfo.setAttrDefs(classInfoMap.get(classId).getAttrDefs());
                    ciInfo.setCiClass(classInfoMap.get(classId).getCiClass());
                }
            }
            ccCiInfos.add(ciInfo);
        }
        return ccCiInfos;
    }


    @Override
    public List<EamCiRltDTO> getHistroyRltInfoByDiagramId(String diagramId, String sheetId) {
        // 获取视图发布信息
        List<ESDiagram> listByQuery = esDiagramDao.getListByQuery(QueryBuilders.termQuery("dEnergy.keyword", diagramId));
        if (CollectionUtils.isEmpty(listByQuery)) {
            // 视图信息异常时直接返回空数据给前端 防止页面弹窗
            return new ArrayList<>();
        }
        // 根据视图的eid 获取对应的 CI / RLT 数据
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("dEnergy.keyword", diagramId));
        if (!BinaryUtils.isEmpty(sheetId)) {
            boolQueryBuilder.must(QueryBuilders.termQuery("sheetId.keyword", sheetId));
        }
        List<ESDiagramLink> linkList = iamsEsDiagramLinkDao.getListByQuery(boolQueryBuilder);
        Map<String, ESDiagramLink> linkCodeAndDataMap = new HashMap<>();
        Set<String> noVersionRltList = new HashSet<>();

        Set<String> privateRltCodeList = new HashSet<>();       // 用于私有库查询

        linkList.forEach(link -> {
            if (BinaryUtils.isEmpty(link.getUniqueCode())) {
                log.info("####### 当前节点为图形 未绑定数据 linkId = " + link.getId() + " #######");
            } else {
                if (BinaryUtils.isEmpty(link.getVersion())) {
                    noVersionRltList.add(link.getUniqueCode());
                } else {
                    linkCodeAndDataMap.put(link.getUniqueCode(), link);
                }
                privateRltCodeList.add(link.getUniqueCode());
            }
        });

        List<EamCiRltDTO> data = new ArrayList<>();
        // 关系数据同样区分本地的数据模式查询
        ESDiagram diagram = listByQuery.get(0);
        if (diagram.getIsOpen() == 0) {
            if (CollectionUtils.isEmpty(privateRltCodeList)) {
                return new ArrayList<>();
            }
            ESRltSearchBean esRltSearchBean = new ESRltSearchBean();
            esRltSearchBean.setRltUniqueCodes(privateRltCodeList);
            esRltSearchBean.setPageNum(1);
            // 关系线段可能存在重复 重复原因未排查到 不能根据code数量查询 因为转化关系线的方法只查询了2000条ci 这里先固定查询1000条rlt
            esRltSearchBean.setPageSize(1000);
            if (diagram.getFlowStatus() != null && diagram.getFlowStatus() != 0) {
                esRltSearchBean.setOwnerCode(listByQuery.get(0).getOwnerCode());
            }else {
                esRltSearchBean.setOwnerCode(SysUtil.getCurrentUserInfo().getLoginCode());
            }
            Page<CcCiRltInfo> ccCiRltInfoPage = iamsCIRltPrivateSvc.searchRltByBean(esRltSearchBean);
            List<CcCiRltInfo> noVersionRltInfos = ccCiRltInfoPage.getData();

            // 获取分类ID 根据ID查询分类信息 回显数据
            List<Long> rltClassIdList = new ArrayList<>();
            noVersionRltInfos.forEach(rltInfo -> {
                rltClassIdList.add(rltInfo.getCiRlt().getClassId());
            });

            Map<Long, CcCiClass> ciClassMap = this.getCcCiClassMapByIds(rltClassIdList);

            // 手动拼接 ciClass 字段
            noVersionRltInfos.forEach(rltInfo -> {
                EamCiRltDTO eamCiRltDTO = new EamCiRltDTO();
                eamCiRltDTO.setCiRlt(rltInfo.getCiRlt());
                eamCiRltDTO.setAttrs(rltInfo.getAttrs());
                eamCiRltDTO.setSourceCiInfo(rltInfo.getSourceCiInfo());
                eamCiRltDTO.setTargetCiInfo(rltInfo.getTargetCiInfo());
                eamCiRltDTO.setCiClass(ciClassMap.get(rltInfo.getCiRlt().getClassId()));
                data.add(eamCiRltDTO);
            });
        } else {
            if (MapUtils.isEmpty(linkCodeAndDataMap)) {
                //
            } else {
                // 根据 version 和 uniqueCode 查询RLT数据
                // 循环放入查询条件
                BoolQueryBuilder queryOrAttrs = QueryBuilders.boolQuery();
                for (String linkCode : linkCodeAndDataMap.keySet()) {
                    BoolQueryBuilder oneQuery = QueryBuilders.boolQuery();
                    oneQuery.must(QueryBuilders.termQuery("version", linkCodeAndDataMap.get(linkCode).getVersion()));
                    oneQuery.must(QueryBuilders.termQuery("uniqueCode.keyword", linkCode));
                    queryOrAttrs.should(oneQuery);
                }
                List<ESCIRltInfoHistory> historyRltList = iamsESCIRltInfoHistoryDesignSvc.getListByQuery(queryOrAttrs);
                // 这里的逻辑同上面的历史CI查询一样
                if (historyRltList.size() != linkCodeAndDataMap.keySet().size()) {
                    List<String> uniqueCodes = historyRltList.stream().map(ESCIRltInfoHistory::getUniqueCode).collect(Collectors.toList());
                    for (String uniqueCode : linkCodeAndDataMap.keySet()) {
                        if (!uniqueCodes.contains(uniqueCode)) {
                            noVersionRltList.add(uniqueCode);
                        }
                    }
                }
                // 返回的格式不咋利索 先挑有用的转化吧
                List<EamCiRltDTO> ccCiRltInfos = this.coverRltHisInfoToESInfo(historyRltList, LibType.DESIGN, null);
                data.addAll(ccCiRltInfos);
            }

            if (!CollectionUtils.isEmpty(noVersionRltList)) {
                ESRltSearchBean esRltSearchBean = new ESRltSearchBean();
                esRltSearchBean.setRltUniqueCodes(noVersionRltList);
                esRltSearchBean.setPageNum(1);
                esRltSearchBean.setPageSize(1000);
                Page<CcCiRltInfo> ccCiRltInfoPage = iamsCIRltDesignSvc.searchRltByBean(esRltSearchBean);
                List<CcCiRltInfo> noVersionRltInfos = ccCiRltInfoPage.getData();

                if (!CollectionUtils.isEmpty(noVersionRltInfos)) {
                    // 获取分类ID 根据ID查询分类信息 回显数据
                    List<Long> rltClassIdList = new ArrayList<>();
                    noVersionRltInfos.forEach(rltInfo -> {
                        rltClassIdList.add(rltInfo.getCiRlt().getClassId());
                    });

                    Map<Long, CcCiClass> ciClassMap = this.getCcCiClassMapByIds(rltClassIdList);

                    // 手动拼接 ciClass 字段
                    noVersionRltInfos.forEach(rltInfo -> {
                        EamCiRltDTO eamCiRltDTO = new EamCiRltDTO();
                        eamCiRltDTO.setCiRlt(rltInfo.getCiRlt());
                        eamCiRltDTO.setAttrs(rltInfo.getAttrs());
                        eamCiRltDTO.setSourceCiInfo(rltInfo.getSourceCiInfo());
                        eamCiRltDTO.setTargetCiInfo(rltInfo.getTargetCiInfo());
                        eamCiRltDTO.setCiClass(ciClassMap.get(rltInfo.getCiRlt().getClassId()));
                        data.add(eamCiRltDTO);
                    });
                    // data.addAll(noVersionRltInfos);
                }
            }
        }
        return data;
    }

    @Override
    public List<EamCiRltDTO> getHistroyRltInfoByDiagramIdWithoutCI(String diagramId, String sheetId) {
        // 获取视图发布信息
        List<ESDiagram> listByQuery = esDiagramDao.getListByQuery(QueryBuilders.termQuery("dEnergy.keyword", diagramId));
        if (CollectionUtils.isEmpty(listByQuery)) {
            // 视图信息异常时直接返回空数据给前端 防止页面弹窗
            return new ArrayList<>();
        }
        // 根据视图的eid 获取对应的 CI / RLT 数据
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("dEnergy.keyword", diagramId));
        if (!BinaryUtils.isEmpty(sheetId)) {
            boolQueryBuilder.must(QueryBuilders.termQuery("sheetId.keyword", sheetId));
        }
        List<ESDiagramLink> linkList = iamsEsDiagramLinkDao.getListByQuery(boolQueryBuilder);
        Map<String, ESDiagramLink> linkCodeAndDataMap = new HashMap<>();
        Set<String> noVersionRltList = new HashSet<>();

        Set<String> privateRltCodeList = new HashSet<>();       // 用于私有库查询

        linkList.forEach(link -> {
            if (BinaryUtils.isEmpty(link.getUniqueCode())) {
                log.info("####### 当前节点为图形 未绑定数据 linkId = " + link.getId() + " #######");
            } else {
                if (BinaryUtils.isEmpty(link.getVersion())) {
                    noVersionRltList.add(link.getUniqueCode());
                } else {
                    linkCodeAndDataMap.put(link.getUniqueCode(), link);
                }
                privateRltCodeList.add(link.getUniqueCode());
            }
        });

        List<EamCiRltDTO> data = new ArrayList<>();
        ESDiagram diagram = listByQuery.get(0);
        // 关系数据同样区分本地的数据模式查询
        if (diagram.getIsOpen() == 0) {
            if (CollectionUtils.isEmpty(noVersionRltList)) {
                return new ArrayList<>();
            }
            ESRltSearchBean esRltSearchBean = new ESRltSearchBean();
            esRltSearchBean.setRltUniqueCodes(privateRltCodeList);
            esRltSearchBean.setPageNum(1);
            esRltSearchBean.setPageSize(privateRltCodeList.size());
            esRltSearchBean.setOwnerCode(SysUtil.getCurrentUserInfo().getLoginCode());
            //流程中的视图放开查看私有库关系数据
            if (diagram.getFlowStatus() != null && diagram.getFlowStatus() == 2) {
                esRltSearchBean.setOwnerCode(diagram.getOwnerCode());
            }
            Page<ESCIRltInfo> ccCiRltInfoPage = iamsCIRltPrivateSvc.searchRltByBeanWioutCI(esRltSearchBean);
            List<ESCIRltInfo> noVersionRltInfos = ccCiRltInfoPage.getData();
            if (!CollectionUtils.isEmpty(noVersionRltInfos)) {
                List<String> userCodes = noVersionRltInfos.stream().map(ESCIRltInfo::getOwnerCode).distinct().collect(Collectors.toList());
                CSysUser cdt = new CSysUser();
                String[] codes = userCodes.toArray(new String[userCodes.size()]);
                cdt.setLoginCodes(codes);
                List<SysUser> sysUserByCdt = userSvc.getSysUserByCdt(cdt);
                Map<String, SysUser> userMap = sysUserByCdt.stream().collect(Collectors.toMap(SysUser::getLoginCode, each -> each));
                noVersionRltInfos.forEach(rltInfo -> {
                    EamCiRltDTO eamCiRltDTO = new EamCiRltDTO();
                    eamCiRltDTO.setCiRlt(rltInfo);
                    Map<String, String> attrs = rltInfo.getAttrs();
                    if (attrs == null) {
                        attrs = new HashMap<>();
                    }
                    String userName = "admin";
                    SysUser currentUser = userMap.get(rltInfo.getOwnerCode());
                    if (!BinaryUtils.isEmpty(currentUser)) {
                        userName = currentUser.getUserName() + "(" + currentUser.getLoginCode() + ")";
                    }
                    attrs.put("所属用户", userName);
                    eamCiRltDTO.setAttrs(attrs);
                    //ci关系属性挪外面，与ci查询接口返回结构保持一致，前端统一从外层拿属性
                    rltInfo.setAttrs(null);
                    data.add(eamCiRltDTO);
                });
            }
        } else {
            if (MapUtils.isEmpty(linkCodeAndDataMap)) {
                //
            } else {
                // 根据 version 和 uniqueCode 查询RLT数据
                // 循环放入查询条件
                BoolQueryBuilder queryOrAttrs = QueryBuilders.boolQuery();
                for (String linkCode : linkCodeAndDataMap.keySet()) {
                    BoolQueryBuilder oneQuery = QueryBuilders.boolQuery();
                    oneQuery.must(QueryBuilders.termQuery("version", linkCodeAndDataMap.get(linkCode).getVersion()));
                    oneQuery.must(QueryBuilders.termQuery("uniqueCode.keyword", linkCode));
                    queryOrAttrs.should(oneQuery);
                }
                List<ESCIRltInfoHistory> historyRltList = iamsESCIRltInfoHistoryDesignSvc.getListByQuery(queryOrAttrs);
                // 这里的逻辑同上面的历史CI查询一样
                if (historyRltList.size() != linkCodeAndDataMap.keySet().size()) {
                    List<String> uniqueCodes = historyRltList.stream().map(ESCIRltInfoHistory::getUniqueCode).collect(Collectors.toList());
                    for (String uniqueCode : linkCodeAndDataMap.keySet()) {
                        if (!uniqueCodes.contains(uniqueCode)) {
                            noVersionRltList.add(uniqueCode);
                        }
                    }
                }
                // 返回的格式不咋利索 先挑有用的转化吧
                for (ESCIRltInfoHistory esciRltInfoHistory : historyRltList) {
                    EamCiRltDTO eamCiRltDTO = new EamCiRltDTO();
                    String jsonStr = JSON.toJSONString(esciRltInfoHistory, SerializerFeature.WriteMapNullValue).replaceAll("null", "''");
                    JSONObject json = JSON.parseObject(jsonStr);
                    ESCIRltInfo rltInfo = JSON.toJavaObject(json, ESCIRltInfo.class);
                    eamCiRltDTO.setAttrs(esciRltInfoHistory.getAttrs());
                    //ci关系属性挪外面，与ci查询接口返回结构保持一致，前端统一从外层拿属性
                    rltInfo.setAttrs(null);
                    eamCiRltDTO.setCiRlt(rltInfo);
                    data.add(eamCiRltDTO);
                }
            }

            if (!CollectionUtils.isEmpty(noVersionRltList)) {
                ESRltSearchBean esRltSearchBean = new ESRltSearchBean();
                esRltSearchBean.setRltUniqueCodes(noVersionRltList);
                esRltSearchBean.setPageNum(1);
                esRltSearchBean.setPageSize(noVersionRltList.size());
                Page<ESCIRltInfo> ccCiRltInfoPage = iamsCIRltDesignSvc.searchRlt(esRltSearchBean);
                List<ESCIRltInfo> noVersionRltInfos = ccCiRltInfoPage.getData();

                if (!CollectionUtils.isEmpty(noVersionRltInfos)) {
                    // 手动拼接
                    noVersionRltInfos.forEach(rltInfo -> {
                        EamCiRltDTO eamCiRltDTO = new EamCiRltDTO();
                        eamCiRltDTO.setCiRlt(rltInfo);
                        eamCiRltDTO.setAttrs(rltInfo.getAttrs());
                        //ci关系属性挪外面，与ci查询接口返回结构保持一致，前端统一从外层拿属性
                        rltInfo.setAttrs(null);
                        data.add(eamCiRltDTO);
                    });
                }
            }
        }
        return data;
    }

    /**
     *  根据classIds查询分类信息map
     * @param rltClassIdList
     * @return
     */
    private Map<Long, CcCiClass> getCcCiClassMapByIds (List<Long> rltClassIdList) {
        if (rltClassIdList.size() == 0) {
            return new HashMap<>();
        }
        CCcCiClass cdt = new CCcCiClass();
        cdt.setIds(rltClassIdList.toArray(new Long[rltClassIdList.size()]));
        List<CcCiClassInfo> ccCiClassInfos = esRltClassSvc.queryClassByCdt(1, rltClassIdList.size(), cdt);
        Map<Long, CcCiClass> ciClassMap = new HashMap<>();
        ccCiClassInfos.forEach(ciClassInfo -> {
            ciClassMap.put(ciClassInfo.getCiClass().getId(), ciClassInfo.getCiClass());
        });
        return ciClassMap;
    }

    @Override
    public Map<String, List<EamReleaseHistoryDTO>> queryHistoryDiagramInfoByIds(Map<String, List<Integer>> param) {
        // 根据设计库视图ID查询和对应的版本号查询历史版本视图信息 支持批量查询

        // 校验传参ID是否合法
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termsQuery("dEnergy.keyword", param.keySet()));
        Page<ESDiagram> diagramPage = diagramApiClient.selectListByQuery(1, param.keySet().size(), query);
        if (diagramPage.getData().size() != param.keySet().size()) {
            throw new BinaryException("视图已经被删除，请进入编辑页面重新选择!");
        }

        // 查询历史版本
        BoolQueryBuilder queryHistoryInfo = QueryBuilders.boolQuery();
        queryHistoryInfo.must(QueryBuilders.termsQuery("releaseDiagramId.keyword", param.keySet()));
        queryHistoryInfo.must(QueryBuilders.termQuery("isOpen", 1));

        List<ESDiagram> listByQuery = esDiagramDao.getListByQuery(queryHistoryInfo);
        if (BinaryUtils.isEmpty(listByQuery)) {
            return Collections.emptyMap();
        }

        List<Long> ids = new ArrayList<>();
        for (ESDiagram esDiagram : listByQuery) {
            if (param.get(esDiagram.getReleaseDiagramId()).contains(esDiagram.getReleaseVersion())) {
                ids.add(esDiagram.getId());
            }
        }

        //查询视图全量信息
        List<ESDiagramDTO> diagramList = diagramApiClient.queryDiagramInfoByIds(ids.toArray(new Long[ids.size()]), "FX_D_HISTORY", false, false);
        diagramList.sort(Comparator.comparing(diagram -> diagram.getDiagram().getReleaseVersion()));
        List<EamReleaseHistoryDTO> historyList = new ArrayList<>();
        String[] userSet = diagramList.stream().map(ESDiagramDTO::getDiagram).map(ESDiagramInfoDTO::getOwnerCode).distinct().toArray(String[]::new);
        CSysUser userCdt = new CSysUser();
        userCdt.setDomainId(1L);
        userCdt.setLoginCodes(userSet);
        userCdt.setSuperUserFlags(new Integer[]{0, 1});
        List<SysUser> cops = userApiSvc.getSysUserByCdt(userCdt);
        Map<String, SysUser> userMap = cops.stream().collect(Collectors.toMap(SysUser::getLoginCode, each -> each, (k1, k2) -> k1));
        for (ESDiagramDTO diagramInfo : diagramList) {
            ESDiagramInfoDTO diagram = diagramInfo.getDiagram();
            EamReleaseHistoryDTO history = new EamReleaseHistoryDTO();
            history.setReleaseUser(userMap.get(diagram.getOwnerCode()));
            com.uinnova.product.eam.comm.model.es.EamDiagramRelease releaseInfo = new EamDiagramRelease();
            diagram.setCreator(diagram.getCreator());
            diagram.setOwnerCode(diagram.getOwnerCode());
            releaseInfo.setDiagram(diagram);
            releaseInfo.setCreateTime(diagram.getOpenTime());
            releaseInfo.setVersionNo(diagramList.size()==1?1:diagram.getReleaseVersion());
            releaseInfo.setDEnergy(diagram.getDEnergy());
            if (!StringUtils.isEmpty(diagram.getReleaseDesc())) {
                releaseInfo.setReleaseDesc(diagram.getReleaseDesc());
            }
            history.setReleaseInfo(releaseInfo);
            historyList.add(history);
        }
        // 返回值根据视图releaseDiagramId字段分组
        Map<String, List<EamReleaseHistoryDTO>> result = historyList.stream().collect(Collectors.groupingBy(e -> e.getReleaseInfo().getDiagram().getReleaseDiagramId()));
        return result;
    }

    /**
     *  将CI的esHistroyInfo格式的数据转换成esInfo格式
     * @param esciHistoryInfos
     * @param classIdAndDataMap
     * @return
     */
    public List<CcCiInfo> coverCIHisInfoToCIInfo(List<ESCIHistoryInfo> esciHistoryInfos, Map<Long, CcCiClassInfo> classIdAndDataMap) {
        if (CollectionUtils.isEmpty(esciHistoryInfos)) {
            return new ArrayList<>();
        }
        List<CcCiInfo> ccCiInfos = new ArrayList<>();
        for (ESCIHistoryInfo esCI : esciHistoryInfos) {
            String jsonStr = JSON.toJSONString(esCI, SerializerFeature.WriteMapNullValue).replaceAll("null", "''");
            JSONObject json = JSON.parseObject(jsonStr);
            CcCiInfo ciInfo = JSON.toJavaObject(json, CcCiInfo.class);

            // 转换映射之后的attrs
            Map<String, String> attrs = new HashMap<>();

            Map<String, String> defIdAndName = new HashMap<>();
            for (CcCiAttrDef ciAttrDef : classIdAndDataMap.get(esCI.getClassId()).getAttrDefs()) {
                defIdAndName.put(ciAttrDef.getId().toString(), ciAttrDef.getProName());
            }
            // 去映射表中查询数据
            List<ESCIAttrTransConfig> attrTransConfigSvcs = attrConfigSvc.getListByQuery(QueryBuilders.termsQuery("defId", defIdAndName.keySet()));
            Map<String, String> oldAndNewId = new HashMap<>();
            if (!BinaryUtils.isEmpty(attrTransConfigSvcs)) {
                for (ESCIAttrTransConfig esciAttrTransConfig : attrTransConfigSvcs) {
                    oldAndNewId.put(esciAttrTransConfig.getTargetAttrName(), esciAttrTransConfig.getSourceAttrName());
                }
            }
            // 检查attrs里的key值，从attrdefs中取proName
            for (String attrKey : ciInfo.getAttrs().keySet()) {
                if (oldAndNewId.containsKey(attrKey)) {
                    attrs.put(oldAndNewId.get(attrKey), ciInfo.getAttrs().get(attrKey));
                } else {
                    attrs.put(attrKey, ciInfo.getAttrs().get(attrKey));
                }
            }
            ciInfo.setAttrs(attrs);

            CcCi ci = JSON.toJavaObject(json, CcCi.class);
            ciInfo.setCi(ci);
            if (!BinaryUtils.isEmpty(classIdAndDataMap.get(esCI.getClassId()))) {
                ciInfo.setCiClass(classIdAndDataMap.get(esCI.getClassId()).getCiClass());
                ciInfo.setAttrDefs(classIdAndDataMap.get(esCI.getClassId()).getAttrDefs());
            }
            ccCiInfos.add(ciInfo);
        }
        return ccCiInfos;
    }

    /**
     *  将RLT的esHistroyInfo格式的数据转换成esInfo格式
     * @param esciRltInfoHistories
     * @param libType 三库标识
     * @return
     */
    @Override
    public List<EamCiRltDTO> coverRltHisInfoToESInfo(List<ESCIRltInfoHistory> esciRltInfoHistories, LibType libType, String userCode) {
        if (CollectionUtils.isEmpty(esciRltInfoHistories)) {
            return new ArrayList<>();
        }
        // 获取源端目标端的CIInfo
        Set<String> targetAndSourceCodeList = new HashSet<>();
        Set<Long> rltClassIds = new HashSet<>();
        esciRltInfoHistories.forEach(rlt -> {
            targetAndSourceCodeList.add(rlt.getTargetCiCode());
            targetAndSourceCodeList.add(rlt.getSourceCiCode());
            rltClassIds.add(rlt.getClassId());
        });

        Map<String, CcCiInfo> targetAndSourceCIMap = new HashMap<>();
        Map<Long, CcCiClassInfo> classIdAndDataMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(targetAndSourceCodeList)) {
            CCcCi cdt = new CCcCi();
            cdt.setCiCodes(targetAndSourceCodeList.toArray(new String[targetAndSourceCodeList.size()]));
            if (libType.equals(LibType.PRIVATE)) {
                cdt.setOwnerCodeEqual(userCode);
            }
            List<CcCiInfo> targetAndSourceCIList = ciSwitchSvc.queryCiInfoList(1L, cdt, null, false, false, libType);
            //查询ci分类
            Map<Long, ESCIClassInfo> clsMap = new HashMap<>();
            Set<Long> ciClassIds = targetAndSourceCIList.stream().map(CcCiInfo::getCi).map(CcCi::getClassId).collect(Collectors.toSet());
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            query.must(QueryBuilders.termsQuery("id", ciClassIds));
            List<ESCIClassInfo> esClassInfos = esciClassSvc.getSortListByQuery(1, 10000, query, null, false).getData();
            if (!CollectionUtils.isEmpty(esClassInfos)) {
                clsMap = esClassInfos.stream().collect(Collectors.toMap(ESCIClassInfo::getId, e -> e));
            }
            for (CcCiInfo ci : targetAndSourceCIList) {
                // 这里查询的源端目标端的数据为最新版本 attrs不准确 前端仅用到分类信息 所以置空
                ci.setAttrs(new HashMap<>());
                if (clsMap.containsKey(ci.getCi().getClassId())) {
                    ci.setAttrDefs(clsMap.get(ci.getCi().getClassId()).getCcAttrDefs());
                    ci.setCiClass(clsMap.get(ci.getCi().getClassId()));
                }
                targetAndSourceCIMap.put(ci.getCi().getCiCode(), ci);
            }
        }

        // 获取rlt分类信息
        // List<ESCIClassInfo> rltClassInfo = esRltClassSvc.getListByQuery(QueryBuilders.termsQuery("id", rltClassIds));
        CCcCiClass cdt = new CCcCiClass();
        cdt.setIds(rltClassIds.toArray(new Long[rltClassIds.size()]));
        List<CcCiClassInfo> rltClassInfo = esRltClassSvc.queryClassByCdt(1, rltClassIds.size(), cdt);
        rltClassInfo.forEach(classinfo -> {
            classIdAndDataMap.put(classinfo.getCiClass().getId(), classinfo);
        });

        List<EamCiRltDTO> data = new ArrayList<>();
        // 进行数据组装
        for (ESCIRltInfoHistory esciRltInfoHistory : esciRltInfoHistories) {
            if (esciRltInfoHistories == null) {
                log.info("####### 历史关系数据转化异常 排查 #######");
            }
            EamCiRltDTO eamCiRltDTO = new EamCiRltDTO();
            String jsonStr = JSON.toJSONString(esciRltInfoHistory, SerializerFeature.WriteMapNullValue).replaceAll("null", "''");
            JSONObject json = JSON.parseObject(jsonStr);
            ESCIRltInfo rltInfo = JSON.toJavaObject(json, ESCIRltInfo.class);
            // 这块拼接的源端目标端的数据暂时查询的是最新的 不是历史版本 前端用到的话要修改成对应的版本数据
            eamCiRltDTO.setTargetCiInfo(targetAndSourceCIMap.get(esciRltInfoHistory.getTargetCiCode()));
            eamCiRltDTO.setSourceCiInfo(targetAndSourceCIMap.get(esciRltInfoHistory.getSourceCiCode()));
            eamCiRltDTO.setAttrs(esciRltInfoHistory.getAttrs());
            eamCiRltDTO.setCiRlt(rltInfo);
            eamCiRltDTO.setCiClass(classIdAndDataMap.get(esciRltInfoHistory.getClassId()).getCiClass());
            data.add(eamCiRltDTO);
        }
        return data;
    }

    /**
     * 获取私有库设计库数据
     *
     * @param esDiagramDTOS
     * @return
     */
    public DiagramPrivateAndDesginData getPrivateAndDesginDataByDEnergyId(List<ESDiagramDTO> esDiagramDTOS, SysUser currentUserInfo) {
        // 根据传参DTO 获取视图数据
        List<ESDiagramInfoDTO> diagramInfoList = new ArrayList<>();
        esDiagramDTOS.forEach(e -> {
            diagramInfoList.add(e.getDiagram());
        });

        // 查询视图上的 CI / RLT 数据 (私有库)
        Set<String> privateCICodes = DataModelDiagramUtil.getDiagramCiList(diagramInfoList);
        Set<String> privateRltCodes = DataModelDiagramUtil.getDiagramRltList(diagramInfoList);
        privateRltCodes.addAll(flowModelMergePreProcessor.queryRltCode(esDiagramDTOS));
        // 根据当前code查询出 私有库 / 设计库 对应数据 并且标记出变更类型
        // 私有库 设计库 数据查询
        List<CcCiInfo> privateCiInfos = new ArrayList<>();
        List<CcCiInfo> desginCiInfos = new ArrayList<>();
        List<ESCIRltInfo> desginRltInfos = new ArrayList<>();
        List<ESCIRltInfo> privateRltInfos = new ArrayList<>();

        if (!BinaryUtils.isEmpty(privateCICodes)) {
            CCcCi cdt = new CCcCi();
            cdt.setCiCodes(privateCICodes.toArray(new String[privateCICodes.size()]));
            desginCiInfos = ciSwitchSvc.queryCiInfoList(currentUserInfo.getDomainId(), cdt, null, false, true, LibType.DESIGN);

            cdt.setOwnerCodeEqual(currentUserInfo.getLoginCode());
            privateCiInfos = ciSwitchSvc.queryCiInfoList(currentUserInfo.getDomainId(), cdt, null, false, true, LibType.PRIVATE);

        }
        if (!BinaryUtils.isEmpty(privateRltCodes)) {
            ESRltSearchBean esRltSearchBean = new ESRltSearchBean();
            esRltSearchBean.setRltUniqueCodes(privateRltCodes);
            esRltSearchBean.setDomainId(currentUserInfo.getDomainId());
            Page<ESCIRltInfo> desginciRltInfoPage = ciRltSwitchSvc.searchRlt(esRltSearchBean, LibType.DESIGN);
            desginRltInfos = desginciRltInfoPage.getData();
            esRltSearchBean.setOwnerCode(currentUserInfo.getLoginCode());
            Page<ESCIRltInfo> privateRltInfoPage = ciRltSwitchSvc.searchRlt(esRltSearchBean, LibType.PRIVATE);
            privateRltInfos = privateRltInfoPage.getData();
        }

        // 返回拼装数据  私有库 / 设计库 CI RLT 数据
        DiagramPrivateAndDesginData data = new DiagramPrivateAndDesginData();
        data.setPrivateCiInfos(privateCiInfos);
        data.setDesginCiInfos(desginCiInfos);
        data.setPrivateRltInfos(privateRltInfos);
        data.setDesginRltInfos(desginRltInfos);
        return data;
    }

    /**
     * 根据查询的变更数据发布视图中的CI要素 -- 强制行为（将私有库数据覆盖到设计库）
     * @param loginCode 用户code
     * @param changeCIDataByDEnergyId 变更类型 -》 CI数据
     * @return
     */
    public List<CcCiInfo> dealPublishDiagramCI(Map<String, List<DiagramChangeData>> changeCIDataByDEnergyId, String loginCode) {
        /*
         *  发布数据处理：
         *       私有库：localVersion归零 publishVersion + 1 （当前publishVersion + 1不针对无修改的数据）
         *
         *       设计库：publishVersion + 1
         * */

        // 获取视图上的 CI 变更数据集
        List<CcCiInfo> ciDataList = new ArrayList<>();
        List<DiagramChangeData> addDataList = changeCIDataByDEnergyId.get("ADD");
        List<DiagramChangeData> updDataList = changeCIDataByDEnergyId.get("UPD");
        List<DiagramChangeData> noDataList = changeCIDataByDEnergyId.get("NO");
        if (CollectionUtils.isEmpty(addDataList) && CollectionUtils.isEmpty(updDataList) && CollectionUtils.isEmpty(noDataList)) {
            return new ArrayList<>();
        }
        // 私有库需要处理的CI数据code集合
        List<String> privateFreshCodes = new ArrayList<>();
        // 根据所有的私有库ciCode去设计库查询CI
        List<String> allPrivateCode = new ArrayList<>();
        List<Long> classIds = new ArrayList<>();

        if (!CollectionUtils.isEmpty(addDataList)) {
            for (DiagramChangeData diagramChangeData : addDataList) {
                CcCiInfo privateCiInfo = diagramChangeData.getPrivateCiInfo();
                privateCiInfo.getCi().setPublicVersion(privateCiInfo.getCi().getPublicVersion() + 1);
                privateCiInfo.getCi().setId(null);
                ciDataList.add(privateCiInfo);
                privateFreshCodes.add(privateCiInfo.getCi().getCiCode());
                classIds.add(privateCiInfo.getCi().getClassId());
                allPrivateCode.add(privateCiInfo.getCi().getCiCode());
            }
        }
        if (!CollectionUtils.isEmpty(updDataList)) {
            for (DiagramChangeData diagramChangeData : updDataList) {
                CcCiInfo privateCiInfo = diagramChangeData.getPrivateCiInfo();
                privateCiInfo.getCi().setPublicVersion(privateCiInfo.getCi().getPublicVersion() + 1);
                privateCiInfo.getCi().setId(null);
                ciDataList.add(privateCiInfo);
                privateFreshCodes.add(privateCiInfo.getCi().getCiCode());
                classIds.add(privateCiInfo.getCi().getClassId());
                allPrivateCode.add(privateCiInfo.getCi().getCiCode());
            }
        }
        // 这里可能存在 当发布版本落后于设计库 本地版本为初始值时 需要强制更新CI数据
        if (!CollectionUtils.isEmpty(noDataList)) {
            for (DiagramChangeData diagramChangeData : noDataList) {
                CcCiInfo privateCiInfo = diagramChangeData.getPrivateCiInfo();
                // 私有库publishVersion < 设计库publishVersion
                if (diagramChangeData.getDesginCiInfo().getCi().getPublicVersion() > diagramChangeData.getPrivateCiInfo().getCi().getPublicVersion()) {
                    privateCiInfo.getCi().setPublicVersion(diagramChangeData.getDesginCiInfo().getCi().getPublicVersion() + 1);
                    iamsESCIPrivateSvc.upgradeVersionNo(privateCiInfo.getCi().getId(), diagramChangeData.getDesginCiInfo().getCi().getPublicVersion());
                    privateCiInfo.getCi().setId(null);
                    ciDataList.add(privateCiInfo);
                    privateFreshCodes.add(privateCiInfo.getCi().getCiCode());       // 在发布视图之前统一升级CI版本号
                    classIds.add(privateCiInfo.getCi().getClassId());
                }
                allPrivateCode.add(privateCiInfo.getCi().getCiCode());
            }
        }
        // 更新私有库localversion为0， publishversion+1
        iamsESCIPrivateSvc.increaseCiPublicVersionByCiCodes(privateFreshCodes, loginCode);

        // 批量更新设计库数据
        List<ESCIInfo> esciInfos = EamUtil.coverCiInfoList(ciDataList);
        if (!CollectionUtils.isEmpty(esciInfos)) {
            ciSwitchSvc.saveOrUpdateBatchCI(esciInfos, classIds, loginCode, loginCode, LibType.DESIGN);
        }

        if (!BinaryUtils.isEmpty(noDataList)) {
            for (DiagramChangeData diagramChangeData : noDataList) {
                privateFreshCodes.add(diagramChangeData.getDesginCiInfo().getCi().getCiCode());
            }
        }

        // 这里要查询所有数据 返回给视图发布绑定CI版本号
        List<CcCiInfo> ccCiInfos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(allPrivateCode)) {
            CCcCi cdt = new CCcCi();
            cdt.setCiCodes(allPrivateCode.toArray(new String[allPrivateCode.size()]));
            ccCiInfos = ciSwitchSvc.queryCiInfoList(1L, cdt, null, false, false, LibType.DESIGN);
        }
        return ccCiInfos;
    }


    /**
     * 根据查询的变更数据发布视图中的RLT关系  ******当前关系发布规则不可下沉至公共组件 仅支持覆盖 需确定需求 *******
     *
     * @param privateAndDesginDataByDEnergyId
     * @return
     */
    public List<ESCIRltInfo> dealPublishDiagramRlt(DiagramPrivateAndDesginData privateAndDesginDataByDEnergyId, List<CcCiInfo> ccCiInfos) {
        Map<String, CcCiInfo> ciCodeAndDataMap = new HashMap<>();
        for (CcCiInfo ccCiInfo : ccCiInfos) {
            ciCodeAndDataMap.put(ccCiInfo.getCi().getCiCode(), ccCiInfo);
        }
        // 获取视图上的 RLT 数据
        List<ESCIRltInfo> privateRltInfos = privateAndDesginDataByDEnergyId.getPrivateRltInfos();       // 私有库
        List<ESCIRltInfo> desginRltInfos = privateAndDesginDataByDEnergyId.getDesginRltInfos();         // 设计库
        Map<String, ESCIRltInfo> desginRltCodeAndDataMap = new HashMap<>();
        for (ESCIRltInfo desginRlt : desginRltInfos) {
            desginRltCodeAndDataMap.put(desginRlt.getCiCode(), desginRlt);
        }
        Set<String> rltCode = new HashSet<>();
        Set<BindCiRltRequestDto> bindCiRltRequestDtos = new HashSet<>();
        List<ESCIRltInfo> updateVersionList = new ArrayList<>();
        for (ESCIRltInfo privateRlt : privateRltInfos) {
            if (desginRltCodeAndDataMap.containsKey(privateRlt.getCiCode())) {
                // 更新处理
                ESCIRltInfo desginRlt = desginRltCodeAndDataMap.get(privateRlt.getCiCode());
                iamsCIRltDesignSvc.updateCiRltAttr(desginRlt.getId(), privateRlt.getAttrs());
                rltCode.add(desginRlt.getCiCode());
                // 这里还需要兼容一下之前的视图 已经创建好关系 没有localVersion字段
                if (BinaryUtils.isEmpty(privateRlt.getLocalVersion())) {
                    // 没有localVersion字段 手动比较attrs的值 判断是否修改
//                    if (!CheckAttrUtil.checkAttrMapEqual(privateRlt.getAttrs(), desginRltCodeAndDataMap.get(privateRlt).getAttrs())) {
//                        privateRlt.setPublicVersion(BinaryUtils.isEmpty(privateRlt.getPublicVersion()) ? 1 : privateRlt.getPublicVersion() + 1);
//                        privateRlt.setLocalVersion(1L);
//                    } else {
//                        // 没有修改过的话
//                        privateRlt.setPublicVersion(1L);
//                        privateRlt.setLocalVersion(1L);
//                    }
                    /*
                     *  修改过attrs
                     *     将本地数据的localVersion置1 publicversion加1（这种数据的publicversion没有值， 下面的操作需要兼容）
                     *     设计库的关系数据从当前时刻开始生成历史数据 之前的没有记录
                     *  没有修改过attrs
                     *     给publicversion理论上设置为1，但是存在其他用户发布的可能，自增加1  将localversion设置为1即可
                     *  所以这里的数据实际上不需要检验修改 可以合并处理
                     *
                     * */
                    privateRlt.setPublicVersion(BinaryUtils.isEmpty(desginRltCodeAndDataMap.get(privateRlt.getCiCode()).getPublicVersion()) ?
                            1 : desginRltCodeAndDataMap.get(privateRlt.getCiCode()).getPublicVersion() + 1);
                    privateRlt.setLocalVersion(1L);
                    updateVersionList.add(privateRlt);
                } else {
                    // 判断私有库localVersion是否增加 去做后续更新处理
                    // 私有库的关系数据 版本号应该统一成 设计库关系数据当前版本号 这里直接+1（不正确） 如果需要加关系冲突校验会有问题 desginRltCodeAndData 的数据版本号需要在发布之前确认为最新的
                    if (privateRlt.getLocalVersion() > 1) {  // 私有库更新过
                        privateRlt.setPublicVersion(BinaryUtils.isEmpty(desginRltCodeAndDataMap.get(privateRlt.getCiCode()).getPublicVersion()) ?
                                1 : desginRltCodeAndDataMap.get(privateRlt.getCiCode()).getPublicVersion() + 1);
                        privateRlt.setLocalVersion(1L);
                        updateVersionList.add(privateRlt);
                    }
                }
            } else {
                // 新建处理
                if (BinaryUtils.isEmpty(ciCodeAndDataMap.get(privateRlt.getTargetCiCode()))) {
                    continue;
                }
                if (BinaryUtils.isEmpty(ciCodeAndDataMap.get(privateRlt.getSourceCiCode()))) {
                    continue;
                }
                BindCiRltRequestDto bindCiRltRequestDto = new BindCiRltRequestDto();
                bindCiRltRequestDto.setTargetCiId(ciCodeAndDataMap.get(privateRlt.getTargetCiCode()).getCi().getId());
                bindCiRltRequestDto.setSourceCiId(ciCodeAndDataMap.get(privateRlt.getSourceCiCode()).getCi().getId());
                bindCiRltRequestDto.setRltClassId(privateRlt.getClassId());
                bindCiRltRequestDto.setAttrs(privateRlt.getAttrs());
                bindCiRltRequestDto.setRepetitionError(false);
                bindCiRltRequestDtos.add(bindCiRltRequestDto);
                // 获取 rlt 的ciCode
                rltCode.add(privateRlt.getCiCode());
                privateRlt.setPublicVersion(BinaryUtils.isEmpty(privateRlt.getPublicVersion()) ? 1 : privateRlt.getPublicVersion() + 1);
                privateRlt.setLocalVersion(1L);
                updateVersionList.add(privateRlt);
            }
        }
        // 批量保存关系数据
        if (!CollectionUtils.isEmpty(bindCiRltRequestDtos)) {
            iamsCIRltDesignSvc.bindCiRlts(SysUtil.getCurrentUserInfo().getDomainId(), bindCiRltRequestDtos, false, null, null);
        }

        // 私有库关系数据发布逻辑与CI保持一致 localVersion = 1 publicversion自增+1
        esCIRltPirvateSvc.saveOrUpdateBatch(updateVersionList);

        // 查询出发布后设计库生成的关系数据 当前代码前提需要保证 两个CI 之间的 一种RLT 数据保持唯一
        if (CollectionUtils.isEmpty(rltCode)) {
            return new ArrayList<>();
        }
        ESRltSearchBean esRltSearchBean = new ESRltSearchBean();
        esRltSearchBean.setRltCodes(rltCode);
        esRltSearchBean.setPageSize(rltCode.size());
        esRltSearchBean.setPageNum(1);
        Page<ESCIRltInfo> esciRltInfoPage = iamsCIRltDesignSvc.searchRlt(esRltSearchBean);
        return esciRltInfoPage.getData();
    }


    /**
     * 处理视图发布
     * @param esDiagramDTOS
     * @param releaseDesc
     * @param
     * @return
     */
    public Map<String, String> dealReleaseDiagram(List<ESDiagramDTO> esDiagramDTOS, String releaseDesc, Map<String, Long> diagramMap, String pointReleaseDiagramId) {
        /*
         *  发布视图逻辑
         *  diagram表中copy一份数据 作为发布的视图 原始图的releaseVersion关联发布的视图
         *
         * */
        Map<String, String> localAndPublishId = new HashMap<>();   // 返回值 本地视图id对应设计库视图id
        for (ESDiagramDTO curDiagramInfo : esDiagramDTOS) {

            ESDiagramInfoDTO curDiagram = curDiagramInfo.getDiagram();
            // 支持盘古业务逻辑 架构资产对应着本地两张id不同的视图文件 pointReleaseDiagramId为盘古发布视图时指定的设计库发布视图
            if (!BinaryUtils.isEmpty(pointReleaseDiagramId)) {
                curDiagram.setReleaseDiagramId(pointReleaseDiagramId);
            }

            String newEnergyId = null;
            if (BinaryUtils.isEmpty(curDiagram.getReleaseDiagramId())) {
                // 初次发布视图
                newEnergyId = this.releaseDiagramStep(curDiagram.getDEnergy(), curDiagram, releaseDesc, diagramMap.get(curDiagramInfo.getDiagram().getDEnergy()), 1);

            } else {
                // copy一份发布的视图设置为历史版本
                Long releaseEnergy = diagramApiClient.queryDiagramInfoByEnergy(curDiagram.getReleaseDiagramId());
                // 根据 releaseDiagramId 查询对应的设计库发布的视图 info
                ESDiagramDTO releaseDiagramInfo = diagramApiClient.queryESDiagramInfoById(releaseEnergy, null, false);
                // 再次发布时 强制将本地视图的 releaseVersion 同步成设计库的数据
                this.synchReleaseVersionData(curDiagramInfo.getDiagram().getDEnergy(), releaseDiagramInfo.getDiagram().getReleaseVersion());
                ESDiagramMoveCdt esDiagramMoveCdt = this.generateDiagram(releaseDiagramInfo.getDiagram(), releaseDiagramInfo.getDiagram().getReleaseDesc(), releaseDiagramInfo.getDiagram().getDirId(), null);
                // copy出历史版本
                newEnergyId = diagramApiClient.copyDiagramById(esDiagramMoveCdt);
                Long historyVersionId = diagramApiClient.queryDiagramInfoByEnergy(newEnergyId);
                esDiagramSvc.writeHistoryVersion(historyVersionId);  // 设置为历史版本
                esDiagramSvc.writeReleaseDiagramId(releaseDiagramInfo.getDiagram().getDEnergy(), historyVersionId);

                // 删除上次发布记录
                this.delDiagramById(releaseDiagramInfo.getDiagram().getId());

                curDiagram.setNewCopyId(releaseDiagramInfo.getDiagram().getId());
                newEnergyId = this.releaseDiagramStep(curDiagram.getDEnergy(), curDiagram, releaseDesc, diagramMap.get(curDiagramInfo.getDiagram().getDEnergy()), 1);

            }
            // 设计库发布视图与本地视图publishVersion +1
            esDiagramSvc.increaseReleaseVersionByDEnergyId(curDiagram.getDEnergy());
            esDiagramSvc.increaseReleaseVersionByDEnergyId(newEnergyId);

            localAndPublishId.put(curDiagram.getDEnergy(), newEnergyId);
        }


        return localAndPublishId;
    }

    /**
     *  发布视图结束后将设计库数据的版本信息记录到视图节点上
     * @param dEnergys
     * @param desginCIList
     * @param desginRltInfo
     * @return
     */
    public Boolean bindCiAndRltVersion (List<String> dEnergys, List<CcCiInfo> desginCIList, List<ESCIRltInfo> desginRltInfo) {
        // 根据dEnergy查询视图的 node 与link 信息
        List<ESDiagramNode> nodeList = iamsEsDiagramNodeDao.getListByQuery(QueryBuilders.termsQuery("dEnergy.keyword", dEnergys));
        List<ESDiagramLink> linkList = iamsEsDiagramLinkDao.getListByQuery(QueryBuilders.termsQuery("dEnergy.keyword", dEnergys));

        Map<String, CcCiInfo> ciCodeAndDataMap = new HashMap<>();
        Map<String, ESCIRltInfo> rltCodeAndDataMap = new HashMap<>();
        desginCIList.forEach(ci -> {
            ciCodeAndDataMap.put(ci.getCi().getCiCode(), ci);
        });
        desginRltInfo.forEach(rlt -> {
            rltCodeAndDataMap.put(rlt.getUniqueCode(), rlt);
        });

        // 直接获取历史表的version字段绑定 其他version不准，只能在对应的库中使用
        if (!MapUtils.isEmpty(ciCodeAndDataMap)) {
            Map<String, Long> ciCodeMaxVersion = iamsESCIHistoryDesignSvc.getCICodeMaxVersion(new ArrayList<>(ciCodeAndDataMap.keySet()));
            // 将 CI RLT 数据绑定到节点信息的version字段上
            for (ESDiagramNode node : nodeList) {
                if (!BinaryUtils.isEmpty(node.getCiCode())) {
                    // 兼容一下异常数据
                    if (!BinaryUtils.isEmpty(ciCodeMaxVersion.get(node.getCiCode()))) {
//                    if (!BinaryUtils.isEmpty(ciCodeAndDataMap.get(node.getCiCode()).getCi().getPublicVersion())) {
//                        // 添加当前ci对应的版本号
//                        node.setVersion(ciCodeAndDataMap.get(node.getCiCode()).getCi().getPublicVersion());
//                    } else {
//                        log.info("############## node 在绑定 ci 版本号时查询到设计库对应数据 但是数据没版本号 nodeId=" + node.getId() + "##############");
//                    }
                        node.setVersion(ciCodeMaxVersion.get(node.getCiCode()));
                    } else {
                        log.info("############## node 在绑定 ci 版本号时未查询到设计库对应数据 nodeId=" + node.getId() + "##############");
                    }
                }
            }
            iamsEsDiagramNodeDao.saveOrUpdateBatch(nodeList);
        }

        if (!MapUtils.isEmpty(rltCodeAndDataMap)) {
            Map<String, Long> uniqueCodeMaxVersion = iamsESCIRltInfoHistoryDesignSvc.getUniqueCodeMaxVersion(new ArrayList<>(rltCodeAndDataMap.keySet()));
            for (ESDiagramLink link : linkList) {
                if (!BinaryUtils.isEmpty(link.getUniqueCode())) {
                    // 兼容一下异常数据
                    if (!BinaryUtils.isEmpty(uniqueCodeMaxVersion.get(link.getUniqueCode()))) {
//                    if (!BinaryUtils.isEmpty(rltCodeAndDataMap.get(link.getUniqueCode()).getPublicVersion())) {
//                        // 添加当前ci对应的版本号
//                        link.setVersion(rltCodeAndDataMap.get(link.getUniqueCode()).getPublicVersion());
//                    } else {
//                        log.info("############## link 在绑定 rlt 版本号时查询到设计库对应数据 但是关系数据没版本号 linkId=" + link.getId() + "##############");
//                    }
                        link.setVersion(uniqueCodeMaxVersion.get(link.getUniqueCode()));
                    } else {
                        log.info("############## link 在绑定 rlt 版本号时未查询到设计库对应数据 linkId=" + link.getId() + "##############");
                    }
                }
            }
            // 更新视图节点数据
            iamsEsDiagramLinkDao.saveOrUpdateBatch(linkList);
        }
        return true;
    }


    public String delDiagramById (Long diagramId) {
        StringBuilder strBuilder = new StringBuilder("删除视图记录：");
        if (BinaryUtils.isEmpty(diagramId)) {
            throw new BinaryException("视图id不能为空");
        }
        ESDiagram esDiagram = esDiagramDao.getById(diagramId);
        //1.根据视图id集合查询视图数据
        EamDiagramQuery query = new EamDiagramQuery();
        query.setId(diagramId);
        Integer deleteDiagramCount = esDiagramDao.deleteByQuery(ESUtil.cdtToBuilder(query), true);
        strBuilder.append("视图是否删除成功：").append(deleteDiagramCount);
        //2.根据视图id集合查询其包含的所有sheet数据
        ESDiagramSheetQuery sheetQuery = new ESDiagramSheetQuery();
        sheetQuery.setDiagramId(diagramId);
        Integer deleteSheetCount = esDiagramSheetDao.deleteByQuery(ESUtil.cdtToBuilder(sheetQuery), true);
        strBuilder.append("sheet是否删除成功：").append(deleteSheetCount);
        //3.查询所有的node节点，将其按照diagramId和sheetId进行分组
        ESDiagramNodeQuery nodeQuery = new ESDiagramNodeQuery();
        nodeQuery.setDiagramId(diagramId);
        Integer deleteNodeCount = iamsEsDiagramNodeDao.deleteByQuery(ESUtil.cdtToBuilder(sheetQuery), true);
        strBuilder.append("node是否删除成功：").append(deleteNodeCount);
        //4.查询所有的link节点，将其按照diagramId和sheetId进行分组
        ESDiagramLinkQuery linkQuery = new ESDiagramLinkQuery();
        linkQuery.setDiagramId(diagramId);
        Integer deleteLinkCount = iamsEsDiagramLinkDao.deleteByQuery(ESUtil.cdtToBuilder(sheetQuery), true);
        strBuilder.append("link是否删除成功：").append(deleteLinkCount);
        return strBuilder.toString();
    }

    public String releaseDiagramStep(String dEnergyId, ESDiagramInfoDTO curDiagram, String releaseDesc, Long dirId, Integer isOpen) {
        ESDiagramMoveCdt esDiagramMoveCdt = this.generateDiagram(curDiagram, releaseDesc, dirId, isOpen);
        String newEnergyId = diagramApiClient.copyDiagramById(esDiagramMoveCdt);
        Long publishDiagramId = diagramApiClient.queryDiagramInfoByEnergy(newEnergyId);
        // 原视图绑定releaseDiagram 新发布视图的EID
        esDiagramSvc.writeReleaseDiagramId(newEnergyId, curDiagram.getId());
        // 新发布视图绑定releaseDiagram 此处绑定当前发布视图的加密id
        esDiagramSvc.writeReleaseDiagramId(newEnergyId, publishDiagramId);
        // 本地视图localVersion 归零
        esDiagramSvc.setLocalVersionByDEnergyIdToZero(curDiagram.getId());
        // 本地视图的flowfStatus设为0
        eamDiagramSvc.changeFlowByDiagramIds(Collections.singletonList(dEnergyId), 0);
        return newEnergyId;
    }

    /**
     * 发布视图
     *
     * @param dEnergyId
     * @param releaseDesc
     * @return
     */
    @Override
    public String publishDiagram(String dEnergyId, String releaseDesc, Long dirId, String releaseDiagramId) {
        List<ESDiagramDTO> esDiagramDTOS = this.queryDiagramInfoByIds(Collections.singletonList(dEnergyId));
        if (esDiagramDTOS.get(0).getDiagram().getIsOpen() == 1) {
            // 查询的列表有问题 原则上设计库的视图不能再发布
            log.info("###########当前单图发布的EID" + dEnergyId);
            return dEnergyId;
        }
        String ownerCode = esDiagramDTOS.get(0).getDiagram().getOwnerCode();
        SysUser userInfoByOwnerCode = this.getUserInfoByOwnerCode(ownerCode);
        // 获取私有库 / 设计库对应数据
        DiagramPrivateAndDesginData privateAndDesginDataByDEnergyId = this.getPrivateAndDesginDataByDEnergyId(esDiagramDTOS, userInfoByOwnerCode);
        // 获取当前视图的 CI 变更数据
        Map<String, List<DiagramChangeData>> changeCIDataByDEnergyId = this.getChangeCIDataByDEnergyIds(esDiagramDTOS, privateAndDesginDataByDEnergyId);
        // 当前CI数据处理
        List<CcCiInfo> ccCiInfos = this.dealPublishDiagramCI(changeCIDataByDEnergyId, ownerCode);       // 【方法返回了CI发布之后对应的设计库数据】
        // 当前关系数据 直接走新建覆盖
        List<ESCIRltInfo> esciRltInfos = this.dealPublishDiagramRlt(privateAndDesginDataByDEnergyId, ccCiInfos);      // 【方法返回了RLT发布之后对应的设计库数据】
        // 视图发布 以及 关联节点关系
        Map<String, Long> diagramMap = new HashMap<>();
        diagramMap.put(dEnergyId, dirId);
        Map<String, String> data = this.dealReleaseDiagram(esDiagramDTOS, releaseDesc, diagramMap, releaseDiagramId);
        // 发布视图的 node 与 link 绑定数据版本信息
        pushFacadeService.bindVersionNoByDiagramId(Collections.singletonList(data.get(dEnergyId)));
        // this.bindCiAndRltVersion(Collections.singletonList(data.get(dEnergyId)), ccCiInfos, esciRltInfos);
        return data.get(dEnergyId);
    }

    /**
     *
     * @param diagram
     * @param releaseDesc
     * @param dirId
     * @param isOpen
     * @return
     */
    public ESDiagramMoveCdt generateDiagram(ESDiagramInfoDTO diagram, String releaseDesc, Long dirId, Integer isOpen) {
        ESDiagramMoveCdt esDiagramMoveCdt = new ESDiagramMoveCdt();
        esDiagramMoveCdt.setNewName(diagram.getName());
//        esDiagramMoveCdt.setNewDirId(diagram.getDirId());
        if (BinaryUtils.isEmpty(dirId)) {
            esDiagramMoveCdt.setNewDirId(0L);
        } else {
            esDiagramMoveCdt.setNewDirId(dirId);
        }
        esDiagramMoveCdt.setDiagramId(diagram.getDEnergy());  // ????
//        esDiagramMoveCdt.setOpType("");    // opType 是个啥玩意 ????
        esDiagramMoveCdt.setViewType(diagram.getViewType());
        esDiagramMoveCdt.setIsOpen(isOpen);
        esDiagramMoveCdt.setReleaseDiagramId(diagram.getReleaseDiagramId());
        esDiagramMoveCdt.setReleaseDesc(releaseDesc);
        esDiagramMoveCdt.setCreateHistory(false);   // 是否为历史版本  ？？？ 还有是否为monet的历史版本
        esDiagramMoveCdt.setCreateHistoryVersion(false);
        esDiagramMoveCdt.setCreateTime(diagram.getCreateTime());
        esDiagramMoveCdt.setOwnerCode(diagram.getOwnerCode());
        // 再次发布是使用原来的加密 ID
        if (!BinaryUtils.isEmpty(diagram.getNewCopyId())) {
            esDiagramMoveCdt.setCopyDiagramId(diagram.getNewCopyId());
        }
        return esDiagramMoveCdt;
    }


    @Override
    public List<String> categoryEleNumCheck(String diagramId, String viewType) {
        // 根据viewType获取制品详细定义信息
        ElementDto elementDto = new ElementDto();
        elementDto.setArtifactId(Long.valueOf(viewType));
        List<EamArtifactElementVo> eamArtifactElementVos = iEamArtifactColumnSvc.queryAllColumns(elementDto);
        // 解析elements字段中的约束信息
        List<String> msgList = this.checkCateNumInfo(eamArtifactElementVos, diagramId);
        return msgList;
    }

    @Override
    public Integer freshPublishDiagramAttr() {
        List<ESDiagram> freashData = new ArrayList<>();

        EamDiagramQuery eamDiagramQuery = new EamDiagramQuery();
        eamDiagramQuery.setIsOpen(1);
        eamDiagramQuery.setDirType(1);
        eamDiagramQuery.setHistoryVersionFlag(1);
        // 查询发布视图主版本的列表数据
        List<ESDiagram> publishDiagramList = esDiagramDao.getListByCdt(eamDiagramQuery);
        eamDiagramQuery.setHistoryVersionFlag(0);
        // 查询发布视图的历史版本列表数据
        List<ESDiagram> publishHistoryDiagramList = esDiagramDao.getListByCdt(eamDiagramQuery);

        // 需要替换的数据从发布视图主版本提取 releaseDiagramId 和 id
        Map<String, String> idMap = new HashMap<>();
        publishDiagramList.forEach(e -> {
            idMap.put(e.getReleaseDiagramId(), e.getDEnergy());
        });

        publishDiagramList.forEach(e -> {
            e.setReleaseDiagramId(e.getDEnergy());
            freashData.add(e);
        });
        publishHistoryDiagramList.forEach(e -> {
            e.setReleaseDiagramId(idMap.get(e.getReleaseDiagramId()));
            freashData.add(e);
        });

        return esDiagramDao.saveOrUpdateBatch(freashData);
    }

    public Map<String, Integer> queryDiagramEleNumById(String diagramId, Set<String> elementList) {
        // 初始化返回数据
        Map<String, Integer> numMap = new HashMap<>();
        for (String element : elementList) {
            numMap.put(element, 0);
        }
        // 根据视图加密ID查询视图node节点
        Long id = diagramApiClient.queryDiagramInfoByEnergy(diagramId);
        ESDiagramNodeQueryBean nodeQueryBean = new ESDiagramNodeQueryBean();
        nodeQueryBean.setDiagramId(id);
        List<ESDiagramNode> nodeList = iamsEsDiagramNodeDao.getListByCdt(nodeQueryBean);
        for (ESDiagramNode node : nodeList) {
            String identName = "";
            JSONObject nodeJson = JSON.parseObject(node.getNodeJson());
            if (!BinaryUtils.isEmpty(nodeJson)) {
                if (!BinaryUtils.isEmpty(nodeJson.get("classId")) && !BinaryUtils.isEmpty(nodeJson.get("classId"))) {
                    if (!BinaryUtils.isEmpty(nodeJson.getString("unique"))) {
                        identName = nodeJson.getString("classId") + nodeJson.getString("unique");
                    } else {
                        identName = nodeJson.getString("classId");
                    }
                } else {
                    if (!BinaryUtils.isEmpty(nodeJson.get("id"))) {
                        identName = nodeJson.getString("id");
                    }
                }
            }
            if (!BinaryUtils.isEmpty(identName) && elementList.contains(identName)) {
                Integer integer = numMap.get(identName);
                numMap.put(identName, integer + 1);
            }
        }
        return numMap;
    }

    /**
     *  批量查询当前视图图内约束CI数量情况
     * @param productNumData 制品ID -》 对应制品的视图集合
     * @param artCondtionNum 制品ID -》 对应的制品约束条件
     * @param idAndNodeInfo 视图id -》 视图上的node信息
     * @return
     */
    public Map<String, Map<String, Integer>> queryDiagramEleNums(Map<Long, List<ESDiagramDTO>> productNumData,
                                                                 Map<Long, Set<String>> artCondtionNum,
                                                                 Map<String, List<ESDiagramNode>> idAndNodeInfo) {

        // 初始化返回数据 将对应的制品的约束的数量设置为0 例：{diagramId：{ciCode + time ：0}}
        Map<String, Map<String, Integer>> artNumMap = new HashMap<>();

        for (Long artId : productNumData.keySet()) {       // 遍历视图信息
            Map<String, Integer> aloneNumMap = new HashMap<>();   // 单图约束数据初始化
            for (ESDiagramDTO esDiagramDTO : productNumData.get(artId)) {
                for (String cond : artCondtionNum.get(artId)) {
                    aloneNumMap.put(cond, 0);
                }
                artNumMap.put(esDiagramDTO.getDiagram().getDEnergy(), aloneNumMap);
            }
        }

        List<Long> ids = new ArrayList<>();
        for (Long artId : productNumData.keySet()) {
            productNumData.get(artId).forEach(e -> {
                ids.add(e.getDiagram().getId());
            });
        }


        Map<String, Long> diagramIdAndArtId = new HashMap<>();        // 在这里获取 视图ID 和 制品ID 对应的map 方便下面获取信息
        // Map<Long, String> idAndEId = new HashMap<>();       // 视图的ID和EID
        for (Long artId : productNumData.keySet()) {
            for (ESDiagramDTO esDiagramDTO : productNumData.get(artId)) {
                diagramIdAndArtId.put(esDiagramDTO.getDiagram().getDEnergy(), artId);
            }
        }
        for (String id : idAndNodeInfo.keySet()) {        // 当前遍历视图ID
            Map<String, Integer> numMap = new HashMap<>();
            for (ESDiagramNode node : idAndNodeInfo.get(id)) {
                String identName = "";
                numMap = artNumMap.get(node.getdEnergy());
                JSONObject nodeJson = JSON.parseObject(node.getNodeJson());
                if (!BinaryUtils.isEmpty(nodeJson)) {
                    if (!BinaryUtils.isEmpty(nodeJson.get("classId")) && !BinaryUtils.isEmpty(nodeJson.get("classId"))) {
                        if (!BinaryUtils.isEmpty(nodeJson.getString("unique"))) {
                            identName = nodeJson.getString("classId") + nodeJson.getString("unique");
                        } else {
                            identName = nodeJson.getString("classId");
                        }
                    } else {
                        if (!BinaryUtils.isEmpty(nodeJson.get("id"))) {
                            identName = nodeJson.getString("id");
                        }
                    }
                }
                if (!BinaryUtils.isEmpty(identName) && artCondtionNum.get(diagramIdAndArtId.get(id)).contains(identName)) {       // 如果图内CI条件不为空 并且 也在对应的制品信息中存在约束 就进行数量记录
                    Integer integer = numMap.get(identName);
                    numMap.put(identName, integer + 1);
                }
            }
            // artNumMap.put(idAndEId.get(id), numMap);        // 视图ID 与 对应的数量
        }
        return artNumMap;
    }

    @Override
    public Map<String, Map<String, String>> extCheckAttrByDiagramIds(List<String> diagramIds, String ownerCode) {
        if (CollectionUtils.isEmpty(diagramIds)) {
            throw new BinaryException("视图id不能为空!");
        }
        // 返回信息 视图id 对应的必填项缺失map结果集
        Map<String, Map<String, String>> data = new HashMap();
        // 根据加密id校验当前批量视图状态
        diagramApiClient.queryDiagramInfoBydEnergy(diagramIds.toArray(new String[diagramIds.size()]));
        // 根据视图id在node索引中查询视图上的资产信息
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termsQuery("dEnergy.keyword", diagramIds));
        List<ESDiagramNode> listByQuery = iamsEsDiagramNodeDao.getListByQuery(boolQueryBuilder);
        if (CollectionUtils.isEmpty(listByQuery)) {
            return data;
        }
        // 视图加密id对应的node信息
        Map<String, List<String>> energyAndNodeCodeList = new HashMap<>();
        List<String> codeList = new ArrayList<>();
        for (String diagramId : diagramIds) {
            List nodeCodes = new ArrayList();
            for (ESDiagramNode esDiagramNode : listByQuery) {
                if (!BinaryUtils.isEmpty(esDiagramNode.getCiCode()) && esDiagramNode.getdEnergy().equals(diagramId)) {
                    nodeCodes.add(esDiagramNode.getCiCode());
                    codeList.add(esDiagramNode.getCiCode());
                }
            }
            if (!BinaryUtils.isEmpty(nodeCodes)) {
                energyAndNodeCodeList.put(diagramId, nodeCodes);
            }
        }
        // 私有库查询对象
        ESCISearchBean bean = new ESCISearchBean();
        bean.setCiCodes(codeList);
        bean.setPageNum(1);
        bean.setPageSize(2000);
        bean.setOwnerCode(ownerCode);
        Page<ESCIInfo> page = ciSwitchSvc.searchESCIByBean(bean, LibType.PRIVATE);

        // 根据当前查询出来的对象数据查询对应的分类id
        Map<String, Long> assetCodeAndClassIdMap = new HashMap<>();
        for (ESCIInfo esciInfo : page.getData()) {
            assetCodeAndClassIdMap.put(esciInfo.getCiCode(), esciInfo.getClassId());
        }
        List<Long> classIds = page.getData().stream().map(ESCIInfo::getClassId).collect(Collectors.toList());
        CCcCiClass cdt = new CCcCiClass();
        cdt.setIds(classIds.toArray(new Long[0]));
        List<CcCiClassInfo> ccCiClassInfos = iciClassApiSvc.queryClassByCdt(cdt);

        Map<Long, CcCiClassInfo> classMap = ccCiClassInfos.stream().collect(Collectors.toMap(each -> each.getCiClass().getId(), each -> each, (k1, k2) -> k2));
        // 遍历对象结果 进行校验
        Map<String, String> errMap = new HashMap<>();
        for (ESCIInfo ci : page.getData()) {
            List<CcCiAttrDef> defs = classMap.get(ci.getClassId()).getAttrDefs();
            Map<String, Integer> errorMsgs = CheckAttrUtil.validateAttrValType(defs, coverToAttrs(ci.getAttrs()));
            if (BinaryUtils.isEmpty(errorMsgs)) {
                continue;
            }
            errMap.put(ci.getCiCode(), errorMsgs.keySet().stream().collect(Collectors.joining("|")));
        }

        // 最后根据视图ID封装返回结果集
        for (String eId : energyAndNodeCodeList.keySet()) {
            Map<String, String> resMap = new HashMap<>();
            for (String ciCode : errMap.keySet()) {
                if (energyAndNodeCodeList.get(eId).contains(ciCode)) {
                    resMap.put(ciCode, errMap.get(ciCode));
                }
            }
            data.put(eId, resMap);
        }
        return data;
    }

    @Override
    public Map<String, List<String>> batchCategoryEleNumCheck(List<String> diagramIds) {
        if (CollectionUtils.isEmpty(diagramIds)) {
            throw new BinaryException("视图id不能为空!");
        }
        // 返回数据视图id对应的视图实例个数校验信息
        Map<String, List<String>> data = new HashMap<>();
        // 根据视图id校验当前视图存在情况
        Long[] ids = diagramApiClient.queryDiagramInfoBydEnergy(diagramIds.toArray(new String[diagramIds.size()]));
        List<ESDiagramDTO> esDiagramDTOList = diagramApiClient.queryDiagramInfoByIds(ids, null, false, false);

        Map<Long, String> eIdAndArtifactMap = new HashMap<>();   // 视图与制品对应的map信息
        List<Long> artifactList = new ArrayList<>();    // 视图的制品集合信息
        for (ESDiagramDTO esDiagramDTO : esDiagramDTOList) {
            if (!BinaryUtils.isEmpty(esDiagramDTO.getDiagram().getViewType())) {
                eIdAndArtifactMap.put(Long.valueOf(esDiagramDTO.getDiagram().getViewType()), esDiagramDTO.getDiagram().getDEnergy());
                artifactList.add(Long.valueOf(esDiagramDTO.getDiagram().getViewType()));
            }
        }
        // 当前发布所有视图没有关联制品 不需要校验
        if (CollectionUtils.isEmpty(artifactList)) {
            return data;
        }

        // 根据viewType获取制品详细定义信息
        Map<Long, List<EamArtifactElementVo>> artifactElementMap = iEamArtifactColumnSvc.queryAllColumnsByIds(artifactList);

        // 遍历制品artifactId 下的key
        for (Long artifactEle : artifactElementMap.keySet()) {
            List<String> msgList = this.checkCateNumInfo(artifactElementMap.get(artifactEle), eIdAndArtifactMap.get(artifactEle));
            data.put(eIdAndArtifactMap.get(artifactEle), msgList);
        }
        return data;
    }

    @Override
    public Map<String, String> batchPublishDiagram(List<String> diagramIds, Map<String, Long> puiblishDirSite) {
        Map<String, String> res = new HashMap<>();      // 返回数据 本地视图ID 和 仓库数据ID

        // 根据ownerCode 先将整体数据做区分 K - 用户 V - 对应的视图集合
        List<ESDiagramDTO> esDiagramDTOS = this.queryDiagramInfoByIds(diagramIds);
        Map<String, List<ESDiagramDTO>> userData = esDiagramDTOS.stream().collect(Collectors.groupingBy(e -> e.getDiagram().getOwnerCode()));       // 用户 和 用户对应的视图数据

        // 本次批量发布所有的视图数据集合 CI/RLT
        List<CcCiInfo> ccCiInfos = new ArrayList<>();
        List<ESCIRltInfo> esCiRltInfos = new ArrayList<>();

        for (String userCode : userData.keySet()) {
            List<ESDiagramDTO> curESDiagramDTOS = userData.get(userCode);

            SysUser userInfoByOwnerCode = this.getUserInfoByOwnerCode(userCode);        // 获取当前用户信息
            // 获取该用户的 私有库 / 设计库 数据
            DiagramPrivateAndDesginData privateAndDesginDataByDEnergyId = this.getPrivateAndDesginDataByDEnergyId(curESDiagramDTOS, userInfoByOwnerCode);
            // 批量获取当前所有视图的 CI 变更数据
            Map<String, List<DiagramChangeData>> changeCIDataByDEnergyId = this.getChangeCIDataByDEnergyIds(curESDiagramDTOS, privateAndDesginDataByDEnergyId);

            // 进入发布数据流程
            List<CcCiInfo> curUserCcCiInfos = this.dealPublishDiagramCI(changeCIDataByDEnergyId, userCode);        // 对当前用户名下的CI进行统一发布
            if (!CollectionUtils.isEmpty(curUserCcCiInfos)) {
                ccCiInfos.addAll(curUserCcCiInfos);
            }
            List<ESCIRltInfo> curUserESCiRltInfos = this.dealPublishDiagramRlt(privateAndDesginDataByDEnergyId, curUserCcCiInfos);// 对当前用户名下的RLT进行统一发布 当前关系数据没有版本概念
            if (!CollectionUtils.isEmpty(curUserESCiRltInfos)) {
                esCiRltInfos.addAll(curUserESCiRltInfos);
            }
            Map<String, String> publishData = this.dealReleaseDiagram(curESDiagramDTOS, null, puiblishDirSite, null);        // 视图发布 以及 关联节点关系
            res.putAll(publishData);
        }
        // 视图节点绑定版本号
        pushFacadeService.bindVersionNoByDiagramId(new ArrayList<>(res.values()));
        // this.bindCiAndRltVersion(new ArrayList<>(res.values()), ccCiInfos, esCiRltInfos);
        return res;
    }

    @Override
    public Boolean refreshPrepareDiagramId() {
        /*
        *  当前接口仅处理当前版本数据 历史版本数据使用其他接口
        *  查询本地 / 和设计库所有当前版本视图
        *  遍历视图：
        *       发布 -- prepareDiagramId = releaseDiagramId
        *       未发布 -- 预制一个ID 【（发布之后releaseDiagramId = prepareDiagramId）】这段逻辑暂时不实现
        *
        * */
        EamDiagramQuery eamDiagramQuery = new EamDiagramQuery();
//        eamDiagramQuery.setIsOpen(0);   // 本地
        eamDiagramQuery.setHistoryVersionFlag(1);   // 当前生效版本
        eamDiagramQuery.setDiagramType(1);
//        eamDiagramQuery.setDirType(1);   // 刷新所有视图
        List<ESDiagram> listByCdt = esDiagramDao.getListByCdt(eamDiagramQuery);
        Map<String, ESDiagram> map = new HashMap<>();
        listByCdt.forEach(e -> {
            map.put(e.getDEnergy(), e);
        });
        listByCdt.forEach(e -> {
            if (BinaryUtils.isEmpty(e.getPrepareDiagramId())) {
                // 如果当前视图未发布 直接设置预制id
                // e.setPrepareDiagramId(IdGenerator.createGenerator().getID() + "");
                if (1 == e.getIsOpen()) {
                    // 设计库 直接等于releaseID
                    e.setPrepareDiagramId(e.getReleaseDiagramId());
                } else {
                    if (!BinaryUtils.isEmpty(e.getReleaseDiagramId())) {
                        e.setPrepareDiagramId(e.getReleaseDiagramId());
                    } else {
                        e.setPrepareDiagramId(IdGenerator.createGenerator().getID() + "");
                    }
                }
            } else {
                // 但前视图发布
                e.setPrepareDiagramId(e.getReleaseDiagramId());
            }
        });
        esDiagramDao.saveOrUpdateBatch(listByCdt);
        return true;
    }

    @Override
    public Map<String, ESDiagramMoveCdt> checkSpikPage(Map<String, Long> data) {
        Map<String, ESDiagramMoveCdt> res = new HashMap<>();
        /*
         *  当前校验跳转需要区分视图数据来源 暂时支持 通用建模 和 组件建模
         *  视图的跳转权限：
         *       关联视图为发布状态 直接跳转到查看页面 lookUp
         *       关联视图为未发布状态 ：
         *               当前用户的或者分享数据 跳转到本地可编辑页面 studio
         *               其他用户未发布的数据 no
         *
         * */
        List<String> generalModelId = new ArrayList<>();   //  通用发布视图
        List<String> componentModelId = new ArrayList<>();   //  组件建模发布视图
        data.keySet().forEach(e -> {
            if (Env.FX_GENERAL_DIR_TYPE == data.get(e).longValue()) {
                generalModelId.add(e);
            }
            if (Env.BM_COMPONENT_DIR_TYPE == data.get(e).longValue()) {
                componentModelId.add(e);
            }
        });

        if (!CollectionUtils.isEmpty(generalModelId)) {
            Map<String, ESDiagramMoveCdt> generalMap = this.checkSkip(generalModelId, Env.FX_GENERAL_DIR_TYPE);    // 校验通用架构视图跳转权限
            res.putAll(generalMap);
        }
        if (!CollectionUtils.isEmpty(componentModelId)) {
            Map<String, ESDiagramMoveCdt> componentMap = this.checkSkip(componentModelId, Env.BM_COMPONENT_DIR_TYPE);    // 校验组件建模视图跳转权限
            res.putAll(componentMap);
        }
        return res;
    }

    /**
     * attrs 属性值转换方法
     *
     * @param attrs
     * @return
     */
    private Map<String, String> coverToAttrs(Map<String, Object> attrs) {
        Map<String, String> newAttrs = new HashMap<>();
        if (BinaryUtils.isEmpty(attrs)) {
            return newAttrs;
        }
        attrs.forEach((k, v) -> {
            if (!BinaryUtils.isEmpty(v)) {
                newAttrs.put(k, String.valueOf(v));
            }
        });
        return newAttrs;
    }

    /**
     * 根据制品类型校验约束条件
     * @param eamArtifactElementVos
     * @param diagramId
     * @return
     */
    public List<String> checkCateNumInfo(List<EamArtifactElementVo> eamArtifactElementVos, String diagramId) {
        List<String> msgList = new ArrayList<>();
        Map<String, ArtifactConstraintVo> elementMap = new HashMap<>();   // 约束信息 与 约束条件
        Set<String> elementList = new HashSet<>();  // 制品图例以及架构元素的约束信息
        List<String> artiElementInfo = new ArrayList<>();  // 制品图例以及架构元素的约束信息
        for (EamArtifactElementVo eamArtifactElementVo : eamArtifactElementVos) {
            artiElementInfo.addAll(eamArtifactElementVo.getElements());
        }

        for (String element : artiElementInfo) {
            JSONObject elementJson = JSON.parseObject(element);
            if (!BinaryUtils.isEmpty(elementJson)) {
                if (!BinaryUtils.isEmpty(elementJson.get("id"))) {
                    String idKey = elementJson.get("id").toString();
                    if (!BinaryUtils.isEmpty(elementJson.get("unique"))) {
                        idKey = idKey + elementJson.get("unique").toString();
                    }
                    elementList.add(idKey);
                    ArtifactConstraintVo constraintVo = new ArtifactConstraintVo();
                    constraintVo.setRelation(elementJson.get("relation").toString());  // 1-等于 2-大于等于 3-小于等于
                    constraintVo.setViewNumber(Integer.valueOf(elementJson.get("viewNumber").toString()));
                    constraintVo.setLabelName(elementJson.get("viewName").toString());
                    elementMap.put(idKey, constraintVo);
                } else {
                    log.info("=========打印当前异常制品节点信息" + element);
                }
            }
        }
        // 根据视图加密ID查询视图上的同种要素数量
        Map<String, Integer> numMap = this.queryDiagramEleNumById(diagramId, elementList);

        for (String ele : elementMap.keySet()) {
            ArtifactConstraintVo artifactConstraintVo = elementMap.get(ele);
            String msg = "";
            if (artifactConstraintVo.getRelation().equals("1")) {
                // 制品约束条件为 =
                if (!artifactConstraintVo.getViewNumber().equals(numMap.get(ele))) {
                    msg = artifactConstraintVo.getLabelName() + "的实例个数必须为" + artifactConstraintVo.getViewNumber();
                }
            } else if (artifactConstraintVo.getRelation().equals("2")) {
                // 制品约束条件为 >=
                if (numMap.get(ele) < artifactConstraintVo.getViewNumber()) {
                    msg = artifactConstraintVo.getLabelName() + "的实例个数必须大于或等于" + artifactConstraintVo.getViewNumber();
                }
            } else if (artifactConstraintVo.getRelation().equals("3")) {
                // 制品约束条件为 <=
                if (numMap.get(ele) > artifactConstraintVo.getViewNumber()) {
                    msg = artifactConstraintVo.getLabelName() + "的实例个数小于或等于" + artifactConstraintVo.getViewNumber();
                }
            }
            if (!BinaryUtils.isEmpty(msg)) {
                msgList.add(msg);
            }
        }
        return msgList;
    }


    /**
     *  批量校验制品数量 传参新增视图上对应的CI个数信息
     * @param columnsByList 制品id -》 制品信息
     * @param productNumData 制品id -》 视图信息
     * @param artCondtionNum 制品id -》 ci约束（ciCode + uniqueTime）
     * @param artCondtions 制品id -》 （ci约束（ciCode + uniqueTime） -》 具体条件）
     * @param idAndNodeInfo 视图id -》 视图上的node信息
     * @return
     */
    public Map<String, List<String>> batchCheckCateNumInfo(Map<Long, List<EamArtifactElementVo>> columnsByList,
                                              Map<Long, List<ESDiagramDTO>> productNumData,
                                              Map<Long, Set<String>> artCondtionNum,
                                              Map<Long, Map<String, ArtifactConstraintVo>> artCondtions,
                                              Map<String, List<ESDiagramNode>> idAndNodeInfo) {

        Map<String, List<String>> numMsgList = new HashMap<>();     // 返回值 视图 和对应的 数量校验信息

        Map<String, Map<String, Integer>> numMap = this.queryDiagramEleNums(productNumData, artCondtionNum, idAndNodeInfo);        // 根据视图加密ID查询视图上的同种要素数量

        for (Long artId : artCondtions.keySet()) {
            for (ESDiagramDTO esDiagramDTO : productNumData.get(artId)) {
                // 这里遍历的视图 下面的约束条件一定是这张视图的
                List<String> msgList = new ArrayList<>();
                for (String ele : artCondtions.get(artId).keySet()) {
                    ArtifactConstraintVo artifactConstraintVo = artCondtions.get(artId).get(ele);
                    String msg = "";
                    if (artifactConstraintVo.getRelation().equals("1")) {
                        // 制品约束条件为 =
                        if (!artifactConstraintVo.getViewNumber().equals(numMap.get(ele))) {
                            msg = artifactConstraintVo.getLabelName() + "的实例个数必须为" + artifactConstraintVo.getViewNumber();
                        }
                    } else if (artifactConstraintVo.getRelation().equals("2")) {
                        // 制品约束条件为 >=
                        if (numMap.get(esDiagramDTO.getDiagram().getDEnergy()).get(ele) < artifactConstraintVo.getViewNumber()) {
                            msg = artifactConstraintVo.getLabelName() + "的实例个数必须大于或等于" + artifactConstraintVo.getViewNumber();
                        }
                    } else if (artifactConstraintVo.getRelation().equals("3")) {
                        // 制品约束条件为 <=
                        if (numMap.get(esDiagramDTO.getDiagram().getDEnergy()).get(ele) > artifactConstraintVo.getViewNumber()) {
                            msg = artifactConstraintVo.getLabelName() + "的实例个数小于或等于" + artifactConstraintVo.getViewNumber();
                        }
                    }
                    if (!BinaryUtils.isEmpty(msg)) {
                        msgList.add(msg);
                    }
                }
                numMsgList.put(esDiagramDTO.getDiagram().getDEnergy(), msgList);
            }
        }
        return numMsgList;
    }

    /**
     * 根据视图详情获取变更数据
     * @param esDiagramDTOS
     * @param privateAndDesginDataByDEnergyId
     * @return
     */
    public Map<String, List<DiagramChangeData>> getChangeCIDataByDEnergyIds(List<ESDiagramDTO> esDiagramDTOS, DiagramPrivateAndDesginData privateAndDesginDataByDEnergyId) {
        /*
         *  根据视图信息获取当前视图的变更及数据
         *  当前视图数据对比设计库分为两类操作数据 新增（ADD） 变更（UPD） 不变（NO）{后期考虑是否添加删除类型数据（DEL）}
         *  返回给上层服务当前视图的所有区别数据 根据上层服务特有的发布逻辑对视图进行处理 确认最终发布视图
         *  返回的数据格式
         *  补充：批量发布 CI/RLT都是以用户为维度创建，所以多张视图可以将结果集融合处理，避免单张处理CI的publishVersion字段反复更新
         *
         *  ADD
         *      CI (私有库， 设计库) ----新增返回数据设计库为空
         *  UPD
         *      CI (私有库， 设计库)
         *  NO
         *      CI (私有库， 设计库)
         *
         * */

        // 返回数据 变更数据集 （ADD UPD）
        Map<String, List<DiagramChangeData>> finalChangeData = new HashMap<>();

        // 此时读取出的数据要保证所有设计库存在的数据都在私有库进行了绑定
        List<CcCiInfo> privateCiInfos = privateAndDesginDataByDEnergyId.getPrivateCiInfos();
        List<CcCiInfo> desginCiInfos = privateAndDesginDataByDEnergyId.getDesginCiInfos();

        List<DiagramChangeData> addData = new ArrayList<>();
        List<DiagramChangeData> updData = new ArrayList<>();
        List<DiagramChangeData> noData = new ArrayList<>();
        // 提取视图中新增的 CI RLT
        if (CollectionUtils.isEmpty(desginCiInfos)) {
            // 当前私有库 CI 都为新增 遍历私有库数据放入返回对象
            for (CcCiInfo privateCI : privateCiInfos) {
                DiagramChangeData diagramChangeData = new DiagramChangeData(privateCI, null, null, null);
                addData.add(diagramChangeData);
            }
            finalChangeData.put("ADD", addData);
            finalChangeData.put("UPD", updData);
            finalChangeData.put("NO", noData);
            return finalChangeData;
        }

        Map<String, CcCiInfo> desginCICodeAndDatas = new HashMap<>();
        for (CcCiInfo desginCI : desginCiInfos) {
            desginCICodeAndDatas.put(desginCI.getCi().getCiCode(), desginCI);
        }
        List<String> filterData = new ArrayList<>();        // 这个是私有库新增的数据code集合
        if (privateCiInfos.size() > desginCiInfos.size()) {
            // 设计库数据不为空 当设计库与私有库数量不一致时 单独筛选出ADD数据
            for (CcCiInfo privateCI : privateCiInfos) {
                if (!desginCICodeAndDatas.containsKey(privateCI.getCi().getCiCode())) {
                    DiagramChangeData diagramChangeData = new DiagramChangeData(privateCI, null, null, null);
                    addData.add(diagramChangeData);
                    filterData.add(privateCI.getCi().getCiCode());
                }
            }
            finalChangeData.put("ADD", addData);
        }

        // 补充UPD NO类型的数据
        /*
         *  循环遍历 私有库 / 设计库 数据 根据私有库的localVersion与publishVersion 和 设计库的 publishVersion 字段判断当前CI的 UPD NO 状态
         *  UPD: 设计库的publishVersion = 私有库的publishVersion localVersion>0时 数据为更新  (当前publishVersion逻辑上已经在发布之前的版本校验与设计库形成统一，设计库与私有库相同)
         *  NO: 设计库的publishVersion = 私有库的publishVersion localVersion=0时 数据为不变
         * */
        for (CcCiInfo privateCI : privateCiInfos) {
            if (!filterData.contains(privateCI.getCi().getCiCode())) {
                // 这部分判断localVersion != 0 原因 新建的CI LV默认会=1 这部分数据已经在上面处理完成 不影响 ，修改的时候自增+1 但是 公共保存CI方法/检出/从画布拖拽设计库对象 时设置LV=0
                if (privateCI.getCi().getLocalVersion() != 0 &&
                privateCI.getCi().getPublicVersion() >= desginCICodeAndDatas.get(privateCI.getCi().getCiCode()).getCi().getPublicVersion()) {
                    // 修改过的数据 标记为 UPD
                    DiagramChangeData diagramChangeData = new DiagramChangeData(privateCI, desginCICodeAndDatas.get(privateCI.getCi().getCiCode()), null, null);
                    updData.add(diagramChangeData);
                } else {
                    // 未修改的数据 标记为 NO 也可能是版本比较低的数据
                    DiagramChangeData diagramChangeData = new DiagramChangeData(privateCI, desginCICodeAndDatas.get(privateCI.getCi().getCiCode()), null, null);
                    noData.add(diagramChangeData);
                }
            }
        }
        finalChangeData.put("NO", noData);
        finalChangeData.put("UPD", updData);

        return finalChangeData;
    }

    /**
     * 根据视图id获取DTO信息
     * @return
     */
    public List<ESDiagramDTO> queryDiagramInfoByIds(List<String> diagramIds) {
        Long[] ids = diagramApiClient.queryDiagramInfoBydEnergy(diagramIds.toArray(new String[diagramIds.size()]));
        List<ESDiagramDTO> esDiagramDTOS = diagramApiClient.queryDiagramInfoByIds(ids, null, false, false);
        for (ESDiagramDTO diagramDTO : esDiagramDTOS) {
            if (BinaryUtils.isEmpty(diagramDTO.getDiagram().getPrepareDiagramId())) {
                throw new BinaryException("当前视图发布缺少预制字段，请联系发布视图管理员");
            }
        }
        return esDiagramDTOS;
    }

    @Override
    public String generalCheckOutDiagram(String diagramId, Long dirId, Integer actionType, String diagramName) {
        /*
        *   检出提示为前端强制提示 后端处理数据
        * */
        String checkId = null;
        List<ESDiagramDTO> esDiagramDTOS = this.queryDiagramInfoByIds(Collections.singletonList(diagramId));   // 查询设计库数据
        DiagramPrivateAndDesginData privateAndDesginDataByDEnergyId = this.getPrivateAndDesginDataByDEnergyId(esDiagramDTOS, SysUtil.getCurrentUserInfo());   // 查询两库数据

        List<CcCiInfo> privateCIInfoList = this.dealCheckOutDiagramCI(privateAndDesginDataByDEnergyId);     // 处理 设计库 / 私有库 CI 数据   当前数据为通过一致性校验结果
        this.dealCheckOutDiagramRLT(privateAndDesginDataByDEnergyId, privateCIInfoList);        // 处理 RLT 数据 没有创建 有更新

        String loginCode = SysUtil.getCurrentUserInfo().getLoginCode();
        List<ESDiagram> listByCdt = new ArrayList<>();
        // 根据发布视图的 ID 判断本地是否存在关联视图
        if (actionType != Env.GENERAL_DIAGRAM_COPY) {
            EamDiagramQuery eamDiagramQuery = new EamDiagramQuery();
            eamDiagramQuery.setIsOpen(0);
            eamDiagramQuery.setOwnerCodeEqual(loginCode);
            eamDiagramQuery.setReleaseDiagramId(diagramId);
            eamDiagramQuery.setHistoryVersionFlag(1);
            eamDiagramQuery.setStatus(1);
            eamDiagramQuery.setDataStatus(1);
            listByCdt = esDiagramDao.getListByCdt(eamDiagramQuery);
            // 重新定义 actionType
            if (!CollectionUtils.isEmpty(listByCdt)) {
                actionType = Env.GENERAL_DIAGRAM_CHECK_OUT_COVER;
            } else {
                actionType = Env.GENERAL_DIAGRAM_CHECK_OUT;
            }
        }
        // 处理 DIAGRAM 数据
        ESDiagramDTO publishDiagramInfo = esDiagramDTOS.get(0);
        ESDiagramMoveCdt esDiagramMoveCdt = new ESDiagramMoveCdt();
        esDiagramMoveCdt.setDiagramId(diagramId);       // 目标视图ID
        esDiagramMoveCdt.setNewName(publishDiagramInfo.getDiagram().getName());
        esDiagramMoveCdt.setOwnerCode(loginCode);
        esDiagramMoveCdt.setNewDirId(dirId);
        esDiagramMoveCdt.setReleaseDesc(null);      // 发布说明清空
        esDiagramMoveCdt.setIsOpen(0);      // 检出为未发布
        esDiagramMoveCdt.setCreateHistory(false);   // 是否为历史版本  ？？？ 还有是否为monet的历史版本
        esDiagramMoveCdt.setCreateHistoryVersion(false);
        if (actionType == Env.GENERAL_DIAGRAM_CHECK_OUT) {      // 视图检出 本地不存在关联数据情况
            // 以发布的视图为模板 copy一张视图保存到本地
            esDiagramMoveCdt.setReleaseDiagramId(diagramId);        // 关联到设计库视图  没生效 底下刷一下吧。。。。

        } else if (actionType == Env.GENERAL_DIAGRAM_CHECK_OUT_COVER) {     // 视图检出 本地视图存在关联数据情况
            // 生成一张新视图 原本视图设置为历史版本
            ESDiagram esDiagram = listByCdt.get(0);     // 本地对应的视图
//            esDiagramSvc.writeHistoryVersion(esDiagram.getId());        // 原图设置成历史版本
            this.delDiagramById(esDiagram.getId());      // 删除 不要了

            esDiagramMoveCdt.setReleaseDiagramId(diagramId);        // 关联到设计库视图
            esDiagramMoveCdt.setCopyDiagramId(esDiagram.getId());

        } else if (actionType == Env.GENERAL_DIAGRAM_COPY) {        // 视图检出 另存为
            // 以发布的视图为模板 copy一张视图保存到本地 不创建关联关系
            // esDiagramMoveCdt.setReleaseDiagramId(diagramId);        // 关联到设计库视图
            esDiagramMoveCdt.setNewName(diagramName);
            Long prepareId = IdGenerator.createGenerator().getID();
            esDiagramMoveCdt.setPrepareDiagramId(SecureUtil.md5(String.valueOf(prepareId)).substring(8, 24));       // 重置业务主键
        } else {
            // 待补充 ***
        }
        checkId = diagramApiClient.copyDiagramById(esDiagramMoveCdt);

        if (actionType == Env.GENERAL_DIAGRAM_COPY) {
            this.initReleaseVersionData(checkId);       // 检出另存为视图版本设为初始值
        } else {
            this.synchReleaseVersionData(checkId, publishDiagramInfo.getDiagram().getReleaseVersion());     // 同步本地检出视图的版本
        }
        if (actionType != Env.GENERAL_DIAGRAM_COPY) {
            Long id = diagramApiClient.queryDiagramInfoByEnergy(checkId);
            esDiagramSvc.writeReleaseDiagramId(diagramId, id);       // 刷新releaseDiagramId字段
        }
        return checkId;
    }

    @Override
    public List<DiagramChangeData> existCheckConflict(List<String> diagramIds) {
        SysUser currentUserInfo = SysUtil.getCurrentUserInfo();
        // 返回数据 data
        List<DiagramChangeData> nuptialData = new ArrayList<>();
        // 获取视图数据
        List<ESDiagramDTO> esDiagramDTOS = this.queryDiagramInfoByIds(diagramIds);
        DiagramPrivateAndDesginData privateAndDesginDataByDEnergyId = this.getPrivateAndDesginDataByDEnergyId(esDiagramDTOS, currentUserInfo);
        List<CcCiInfo> privateCiInfos = privateAndDesginDataByDEnergyId.getPrivateCiInfos();
        List<CcCiInfo> desginCiInfos = privateAndDesginDataByDEnergyId.getDesginCiInfos();
        if (privateCiInfos.size() == desginCiInfos.size() || BinaryUtils.isEmpty(privateCiInfos)) {
            // 当前数据都绑定到设计库 一一对应
            return new ArrayList<>();
        }

        // CI code与data对应的map
        Map<String, CcCiInfo> privateCodeAndCiInfoMap = new HashMap<>();
        Map<String, CcCiInfo> desginCodeAndCiInfoMap = new HashMap<>();
        for (CcCiInfo privateCI : privateCiInfos) {
            privateCodeAndCiInfoMap.put(privateCI.getCi().getCiCode(), privateCI);
        }
        for (CcCiInfo desginCI : desginCiInfos) {
            desginCodeAndCiInfoMap.put(desginCI.getCi().getCiCode(), desginCI);
        }
        // 筛选出私有库不存在的数据 name
        Map<String, CcCiInfo> existDesginNameAndDataList = new HashMap<>();
        for (CcCiInfo desginCI : desginCiInfos) {
            if (!privateCodeAndCiInfoMap.containsKey(desginCI.getCi().getCiCode())) {
                existDesginNameAndDataList.put(desginCI.getCi().getCiPrimaryKey(), desginCI);
            }
        }
        //设计库根据名称查询是否存在同名要素
        List<ESCIInfo> nameEqualData = new ArrayList<>();

        List<String> ciPrimaryKeys = new ArrayList<>();
        List<Long> classIds = new ArrayList<>();
        existDesginNameAndDataList.values().forEach(e -> {
            ciPrimaryKeys.add(e.getCi().getCiPrimaryKey());
            classIds.add(e.getCi().getClassId());
        });
        if (BinaryUtils.isEmpty(ciPrimaryKeys) || BinaryUtils.isEmpty(classIds)) {
            return new ArrayList<>();
        }
        ESCISearchBean esciSearchBean = new ESCISearchBean();
        esciSearchBean.setCiPrimaryKeys(ciPrimaryKeys);
        esciSearchBean.setClassIds(classIds);
        esciSearchBean.setOwnerCode(currentUserInfo.getLoginCode());
        esciSearchBean.setPageNum(1);
        esciSearchBean.setPageSize(500);
        Page<ESCIInfo> esciInfoPage = ciSwitchSvc.searchESCIByBean(esciSearchBean, LibType.PRIVATE);
        nameEqualData.addAll(esciInfoPage.getData());
        if (CollectionUtils.isEmpty(nameEqualData)) {
            // 设计库无重名要素 不需要检出
            return new ArrayList<>();
        }

        List<String> ciCodes = nameEqualData.stream().map(ESCIInfo::getCiCode).collect(Collectors.toList());
        CCcCi cdt = new CCcCi();
        cdt.setCiCodes(ciCodes.toArray(new String[ciCodes.size()]));
        cdt.setOwnerCodeEqual(currentUserInfo.getLoginCode());
        List<CcCiInfo> ccCiInfos = ciSwitchSvc.queryCiInfoList(currentUserInfo.getDomainId(), cdt, null, false, true, LibType.PRIVATE);

        for (CcCiInfo esciInfo : ccCiInfos) {
            DiagramChangeData diagramChangeData = new DiagramChangeData(existDesginNameAndDataList.get(esciInfo.getCi().getCiPrimaryKey()), esciInfo, null, null);
            nuptialData.add(diagramChangeData);
        }
        return nuptialData;
    }

    @Override
    public Boolean changeFlowByDiagramIds(List<String> eIds, Integer flowStatus) {
        return eamDiagramSvc.changeFlowByDiagramIds(eIds, flowStatus);
    }


    public Map<String, ESDiagramMoveCdt> checkSkip (List<String> pIds, Integer dirType) {
        Map<String, ESDiagramMoveCdt> res = new HashMap<>();
        List<String> publishPIds = new ArrayList<>();
        List<ESDiagram> esDiagramList = new ArrayList<>();
        if (Env.FX_GENERAL_DIR_TYPE == dirType) {
            // 通用视图跳转逻辑
            EamDiagramQuery eamDiagramQuery = new EamDiagramQuery();
            eamDiagramQuery.setIsOpen(1);  // 发布在设计库数据
            eamDiagramQuery.setDataStatus(1);  // 未删除
            eamDiagramQuery.setStatus(1);
            eamDiagramQuery.setHistoryVersionFlag(1);
            eamDiagramQuery.setPrepareDiagramIds(pIds.toArray(new String[pIds.size()]));
            esDiagramList = esDiagramDao.getListByCdt(eamDiagramQuery);
            // 若当前跳转视图已经发布 返回lookUp标识
            publishPIds = esDiagramList.stream().map(ESDiagram::getPrepareDiagramId).collect(Collectors.toList());  // 当前下钻视图ids集合为直接跳转到查看页面数据

            // 只读视图添加
            for (ESDiagram esDiagram : esDiagramList) {
                ESDiagramMoveCdt cdt = new ESDiagramMoveCdt();
                cdt.setDiagramId(esDiagram.getDEnergy());  // 前端跳转使用的ID
                cdt.setOpType("LOOK_UP");  // 标记为只读
                res.put(esDiagram.getPrepareDiagramId(), cdt);
            }
        }
        if (Env.BM_COMPONENT_DIR_TYPE == dirType) {
            // 因为组件建模发布时以图中的主键为维度 所以发布视图的历史版本和主版本的preDiagramId可能存在不同
            EamDiagramQuery eamDiagramQuery = new EamDiagramQuery();
            eamDiagramQuery.setIsOpen(1);  // 发布在设计库数据
            eamDiagramQuery.setDataStatus(1);  // 未删除
            eamDiagramQuery.setStatus(1);
            eamDiagramQuery.setPrepareDiagramIds(pIds.toArray(new String[pIds.size()]));
            List<ESDiagram> esDiagramList1 = esDiagramDao.getListByCdt(eamDiagramQuery);
            // 若当前跳转视图已经发布 返回lookUp标识
            List<String> publishRIds = esDiagramList1.stream().map(ESDiagram::getReleaseDiagramId).collect(Collectors.toList());  // 当前下钻视图ids集合为直接跳转到查看页面数据
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            boolQueryBuilder.must(QueryBuilders.termQuery("isOpen", 1));
            boolQueryBuilder.must(QueryBuilders.termQuery("dataStatus", 1));
            boolQueryBuilder.must(QueryBuilders.termQuery("status", 1));
            boolQueryBuilder.must(QueryBuilders.termQuery("historyVersionFlag", 1));
            boolQueryBuilder.must(QueryBuilders.termsQuery("releaseDiagramId.keyword", publishRIds));
            esDiagramList = esDiagramDao.getListByQuery(boolQueryBuilder);

            // 只读视图添加
            for (ESDiagram esDiagram : esDiagramList) {
                ESDiagramMoveCdt cdt = new ESDiagramMoveCdt();
                cdt.setDiagramId(esDiagram.getDEnergy());  // 前端跳转使用的ID
                cdt.setOpType("LOOK_UP");  // 标记为只读
                res.put(esDiagram.getPrepareDiagramId(), cdt);
            }
        }

        // 过滤掉只读权限的业务主键
        List<String> unPublishPIds = new ArrayList<>();
        for (String id : pIds) {
            if (!publishPIds.contains(id)) {
                unPublishPIds.add(id);
            }
        }

        if (!CollectionUtils.isEmpty(unPublishPIds)) {
            EamDiagramQuery eamDiagramQuery1 = new EamDiagramQuery();
            eamDiagramQuery1.setIsOpen(0);  // 私有库数据
            eamDiagramQuery1.setDataStatus(1);  // 未删除
            eamDiagramQuery1.setStatus(1);
            eamDiagramQuery1.setHistoryVersionFlag(1);
            eamDiagramQuery1.setPrepareDiagramIds(unPublishPIds.toArray(new String[unPublishPIds.size()]));
            eamDiagramQuery1.setOwnerCodeEqual(SysUtil.getCurrentUserInfo().getLoginCode());  // 自己的私有库数据
            List<ESDiagram> listByCdt = esDiagramDao.getListByCdt(eamDiagramQuery1);
            List<String> ownUnPublishIds = listByCdt.stream().map(ESDiagram::getPrepareDiagramId).collect(Collectors.toList());

            // 本地可编辑视图添加
            for (ESDiagram esDiagram : listByCdt) {
                ESDiagramMoveCdt cdt = new ESDiagramMoveCdt();
                cdt.setDiagramId(esDiagram.getDEnergy());  // 前端跳转使用的ID
                cdt.setOpType("STUDIO");  // 标记为可编辑
                res.put(esDiagram.getPrepareDiagramId(), cdt);
            }

            //  过滤掉自己的可编辑的业务主键
            List<String> sharePIds = unPublishPIds.stream().filter(e -> !ownUnPublishIds.contains(e)).collect(Collectors.toList());

            if (!CollectionUtils.isEmpty(sharePIds)) {
                EamDiagramQuery eamDiagramQuery2 = new EamDiagramQuery();
                eamDiagramQuery2.setIsOpen(0);  // 私有库数据
                eamDiagramQuery2.setDataStatus(1);  // 未删除
                eamDiagramQuery2.setStatus(1);
                eamDiagramQuery2.setHistoryVersionFlag(1);
                eamDiagramQuery2.setPrepareDiagramIds(sharePIds.toArray(new String[sharePIds.size()]));
                List<ESDiagram> listByCdt1 = esDiagramDao.getListByCdt(eamDiagramQuery2);
                // 过滤出ID去分享表中比较
                Map<Long, ESDiagram> shareId = listByCdt1.stream().collect(Collectors.toMap(each -> each.getId(), each -> each, (k1, k2) -> k2));
                List<DiagramShareRecord> diagramShareRecords = shareDiagramSvc.queryByUserId(SysUtil.getCurrentUserInfo().getId());

                List<Long> curShareIds = diagramShareRecords.stream().map(DiagramShareRecord::getDiagramId).collect(Collectors.toList());

                for (Long id : shareId.keySet()) {
                    ESDiagramMoveCdt cdt = new ESDiagramMoveCdt();
                    if (curShareIds.contains(id)) {
                        cdt.setDiagramId(shareId.get(id).getDEnergy());  // 前端跳转使用的ID
                        cdt.setOpType("STUDIO");  // 标记为可编辑
                    } else {
                        cdt.setDiagramId(shareId.get(id).getDEnergy());  // 前端跳转使用的ID
                        cdt.setOpType("NO");  // 标记为不可编辑
                    }
                    res.put(shareId.get(id).getPrepareDiagramId(), cdt);
                }
            }
        }
        return res;
    }

    /**
     * 检出处理 CI 数据
     * @param privateAndDesginDataByDEnergyId
     */
    @Override
    public List<CcCiInfo> dealCheckOutDiagramCI(DiagramPrivateAndDesginData privateAndDesginDataByDEnergyId) {

        // 将设计库数据覆盖到私有库数据上 将私有库的数据版本信息同步设计库 初始化私有库的本地版本信息

        List<CcCiInfo> desginCiInfos = privateAndDesginDataByDEnergyId.getDesginCiInfos();      // 设计库数据信息
        List<CcCiInfo> privateCiInfos = privateAndDesginDataByDEnergyId.getPrivateCiInfos();        // 私有库数据信息

        SysUser currentUserInfo = SysUtil.getCurrentUserInfo();     // 获取用户信息

        Map<String, CcCiInfo> privateCiCodesAndInfo = new HashMap<>();        // 私有库 CI Info
        for (CcCiInfo privateInfo : privateCiInfos) {
            privateCiCodesAndInfo.put(privateInfo.getCi().getCiCode(), privateInfo);
        }
        List<Long> classIds = new ArrayList<>();        // classId集合
        List<String> ciCodes = new ArrayList<>();       // 批量保存至私有库的ciCode集合
        List<Long> ciIds = new ArrayList<>();       // 根据ID批量刷新localVersion字段

        List<CcCiInfo> creatOrUpdateCIInfos = new ArrayList<>();        // 保存或者更新到私有库的数据
        for (CcCiInfo desginInfo : desginCiInfos) {
            if (!privateCiCodesAndInfo.containsKey(desginInfo.getCi().getCiCode())) {
                // case1: 若当前设计库数据不存在私有库 直接创建
                desginInfo.getCi().setLocalVersion(0L);     // 用户私有库不存在设计库数据 在私有库创建 localVersion设为初始数值0 publishVersion / ciCode 与设计库保持对应
                desginInfo.getCi().setId(null);
                desginInfo.getCi().setOwnerCode(currentUserInfo.getLoginCode());
                creatOrUpdateCIInfos.add(desginInfo);
                classIds.add(desginInfo.getCi().getClassId());
                ciCodes.add(desginInfo.getCi().getCiCode());
            } else {
                // case2: 若当前设计库数据存在私有库 以设计库数据为准
                CcCiInfo privateCIInfo = privateCiCodesAndInfo.get(desginInfo.getCi().getCiCode());
                privateCIInfo.getCi().setLocalVersion(0L);
                privateCIInfo.getCi().setOwnerCode(currentUserInfo.getLoginCode());
                privateCIInfo.getCi().setPublicVersion(desginInfo.getCi().getPublicVersion());
                privateCIInfo.setAttrs(desginInfo.getAttrs());      // 将私有库存在的数据与设计库进行版本同一，属性统一 localVerrsion设置为初始值0
                creatOrUpdateCIInfos.add(privateCIInfo);
                classIds.add(privateCIInfo.getCi().getClassId());
                ciCodes.add(privateCIInfo.getCi().getCiCode());
                ciIds.add(privateCIInfo.getCi().getId());
            }
        }
        List<CcCiInfo> ciInfos = new ArrayList<>();
        if (CollectionUtils.isEmpty(creatOrUpdateCIInfos)) {
            return ciInfos;
        }
        List<ESCIInfo> esciInfos = EamUtil.coverCiInfoList(creatOrUpdateCIInfos);
        ciSwitchSvc.saveOrUpdateBatchCI(esciInfos, classIds, currentUserInfo.getLoginCode(), currentUserInfo.getLoginCode(), LibType.PRIVATE);      // 批量创建更新至私有库

        iamsESCIPrivateSvc.makeZeroCiLocalVersionByIds(ciIds);      // 批量更新私有库loclaVersion字段失效 这里直接手动刷新为 0

        if (!CollectionUtils.isEmpty(ciCodes)) {
            CCcCi cdt = new CCcCi();
            cdt.setCiCodes(ciCodes.toArray(new String[ciCodes.size()]));
            cdt.setOwnerCodeEqual(currentUserInfo.getLoginCode());
            ciInfos = ciSwitchSvc.queryCiInfoList(currentUserInfo.getDomainId(), cdt, null, false, false, LibType.PRIVATE);       // 查询私有库创建更新数据 用于下一步关系创建
        }
        return ciInfos;
    }

    /**
     *  检出关系处理
     * @param privateAndDesginDataByDEnergyId
     * @param ccCiInfos
     */
    @Override
    public Boolean dealCheckOutDiagramRLT(DiagramPrivateAndDesginData privateAndDesginDataByDEnergyId, List<CcCiInfo> ccCiInfos) {
        Map<String, CcCiInfo> ciCodeAndDataMap = new HashMap<>();
        for (CcCiInfo ccCiInfo : ccCiInfos) {
            ciCodeAndDataMap.put(ccCiInfo.getCi().getCiCode(), ccCiInfo);
        }
        // 获取视图上的 RLT 数据
        List<ESCIRltInfo> privateRltInfos = privateAndDesginDataByDEnergyId.getPrivateRltInfos();
        List<ESCIRltInfo> desginRltInfos = privateAndDesginDataByDEnergyId.getDesginRltInfos();

        Map<String, ESCIRltInfo> privateRltCodeAndDataMap = new HashMap<>();
        for (ESCIRltInfo privateRlt : privateRltInfos) {
            privateRltCodeAndDataMap.put(privateRlt.getCiCode(), privateRlt);
        }
        Set<BindCiRltRequestDto> bindCiRltRequestDtos = new HashSet<>();
        Map<String, Long> desginRltUniqueCodeAndVersionMap = new HashMap<>();            // 设计库关系数据唯一标识UniqueCode 和 publicversion字段
        for (ESCIRltInfo desginRlt : desginRltInfos) {
            if (privateRltCodeAndDataMap.containsKey(desginRlt.getCiCode())) {
                // 更新处理
                ESCIRltInfo privateRlt = privateRltCodeAndDataMap.get(desginRlt.getCiCode());
                Long aLong = ciRltSwitchSvc.updateCiRltAttr(privateRlt.getId(), desginRlt.getAttrs(), LibType.PRIVATE);
            } else {
                // 新建处理
                BindCiRltRequestDto bindCiRltRequestDto = new BindCiRltRequestDto();
                bindCiRltRequestDto.setTargetCiId(ciCodeAndDataMap.get(desginRlt.getTargetCiCode()).getCi().getId());
                bindCiRltRequestDto.setSourceCiId(ciCodeAndDataMap.get(desginRlt.getSourceCiCode()).getCi().getId());
                bindCiRltRequestDto.setRltClassId(desginRlt.getClassId());
                bindCiRltRequestDto.setAttrs(desginRlt.getAttrs());
                bindCiRltRequestDto.setRepetitionError(false);
                bindCiRltRequestDto.setOwnerCode(SysUtil.getCurrentUserInfo().getLoginCode());
                bindCiRltRequestDtos.add(bindCiRltRequestDto);
            }
            if (!BinaryUtils.isEmpty(desginRlt.getPublicVersion())) {    // 之前设计库存在没有历史版本的关系数据忽略 暂时不考虑版本继承
                desginRltUniqueCodeAndVersionMap.put(desginRlt.getUniqueCode(), desginRlt.getPublicVersion());
            }
        }
        // 批量保存关系数据
        if (!CollectionUtils.isEmpty(bindCiRltRequestDtos)) {
            iamsCIRltPrivateSvc.bindCiRlts(SysUtil.getCurrentUserInfo().getDomainId(), bindCiRltRequestDtos, false, null, null);
        }
        // 刷新私有库关系版本 ：localversion置为1 publicversion设置为设计库对应的关系版本号
        if (!MapUtils.isEmpty(desginRltUniqueCodeAndVersionMap)) {
            this.updatePrivateRltVersion(desginRltUniqueCodeAndVersionMap);
        }
        return true;
    }

    /**
     *  刷新私有库关系数据的 publicVersion 字段 为设计库对应版本号 localVersion = 1
     * @param desginRltUniqueCodeAndVersionMap
     * @return
     */
    public Boolean updatePrivateRltVersion (Map<String, Long> desginRltUniqueCodeAndVersionMap) {
        // 根据设计库的唯一标识在私有库查询对应的关系数据 查询操作为了确认私有库确实存在数据
        ESRltSearchBean esRltSearchBean = new ESRltSearchBean();
        esRltSearchBean.setRltUniqueCodes(desginRltUniqueCodeAndVersionMap.keySet());
        esRltSearchBean.setPageNum(1);
        esRltSearchBean.setOwnerCode(SysUtil.getCurrentUserInfo().getLoginCode());
        esRltSearchBean.setPageSize(desginRltUniqueCodeAndVersionMap.keySet().size());
        Page<ESCIRltInfo> esciRltInfoPage = iamsCIRltPrivateSvc.searchRlt(esRltSearchBean);
        List<ESCIRltInfo> data = esciRltInfoPage.getData();
        if (desginRltUniqueCodeAndVersionMap.keySet().size() != data.size()) {
            log.info("######## 当前使用设计库唯一标志字段在私有库查询 数量不一致 排查 ########");
        }
        if (CollectionUtils.isEmpty(data)) {
            log.info("######## 当前使用设计库唯一标志字段在私有库查询 数量为空 排查 ########");
            return true;
        }
        data.forEach(rlt -> {
            rlt.setPublicVersion(desginRltUniqueCodeAndVersionMap.get(rlt.getUniqueCode()));
            rlt.setLocalVersion(1L);
        });
        esCIRltPirvateSvc.saveOrUpdateBatch(data);
        return true;
    }

    public void synchReleaseVersionData(String id, Integer releaseVersion) {
        // 刷新releaseVersion 同步设计库
        StringBuffer script = new StringBuffer(1000);
        script.append("ctx._source.releaseVersion=params.releaseVersion;");
        Map<String,Object> params = new HashMap<>();
        params.put("releaseVersion", releaseVersion);
        esDiagramDao.updateByQuery(QueryBuilders.termQuery("dEnergy.keyword", id), script.toString(), true, params);
    }

    public void initReleaseVersionData(String id) {
        // 刷新releaseVersion = 0
        StringBuffer script = new StringBuffer(1000);
        script.append("ctx._source.releaseVersion=params.releaseVersion;");
        Map<String, Object> params = new HashMap<>();
        params.put("releaseVersion", 0);
        esDiagramDao.updateByQuery(QueryBuilders.termQuery("dEnergy.keyword", id), script.toString(), true, params);
    }


    public SysUser getUserInfoByOwnerCode(String ownerCode) {
        // 当前用户信息
        SysUser currentUserInfo = new SysUser();
        if (BinaryUtils.isEmpty(ownerCode)) {
            currentUserInfo = SysUtil.getCurrentUserInfo();
        } else {
            CSysUser cSysUser = new CSysUser();
            cSysUser.setLoginCodeEqual(ownerCode);
            List<SysUser> sysUserInfo = userApiSvc.getSysUserByCdt(cSysUser);
            if (CollectionUtils.isEmpty(sysUserInfo)) {
                throw new BinaryException("当前视图所属用户不存在!");
            }
            currentUserInfo = sysUserInfo.get(0);
        }
        return currentUserInfo;
    }

    /**
     * 多用户校验CI主键冲突
     * @param data 用户code -》 对应的用户视图信息
     * @param data 用户code -》 对应的用户名下 私有库 / 设计库 数据
     */
    public Map<String, List<DiagramChangeData>> checkPrimaryKeyConflict(Map<String, List<ESDiagramDTO>> data, Map<String, DiagramPrivateAndDesginData> privateAndDesginDataByUserCode) {
        // 目前只能循环用户 检查冲突数据
        Map<String, List<DiagramChangeData>> primaryKeyConflict = new HashMap<>();     // 主键冲突数据返回值
        for (String userCode : data.keySet()) {
            List<DiagramChangeData> nuptialData = new ArrayList<>();        // 当前用户的主键冲突数据 data
            DiagramPrivateAndDesginData privateAndDesginDataByDEnergyId = privateAndDesginDataByUserCode.get(userCode);     // 当前用户的 私有库 / 设计库 数据
            List<CcCiInfo> privateCiInfos = privateAndDesginDataByDEnergyId.getPrivateCiInfos();
            List<CcCiInfo> desginCiInfos = privateAndDesginDataByDEnergyId.getDesginCiInfos();
            if (privateCiInfos.size() == desginCiInfos.size() || BinaryUtils.isEmpty(privateCiInfos)) {
                // 当前数据都绑定到设计库 一一对应
                primaryKeyConflict.put(userCode, nuptialData);
                continue;
            }

            // CI code与data对应的map
            Map<String, CcCiInfo> privateCodeAndCiInfoMap = new HashMap<>();
            Map<String, CcCiInfo> desginCodeAndCiInfoMap = new HashMap<>();
            for (CcCiInfo privateCI : privateCiInfos) {
                privateCodeAndCiInfoMap.put(privateCI.getCi().getCiCode(), privateCI);
            }
            for (CcCiInfo desginCI : desginCiInfos) {
                desginCodeAndCiInfoMap.put(desginCI.getCi().getCiCode(), desginCI);
            }
            // 筛选出设计库不存在的数据 name
            Map<String, CcCiInfo> existPrivateNameAndDataList = new HashMap<>();
            for (CcCiInfo privateCI : privateCiInfos) {
                if (!desginCodeAndCiInfoMap.containsKey(privateCI.getCi().getCiCode())) {
                    existPrivateNameAndDataList.put(privateCI.getCi().getCiPrimaryKey(), privateCI);
                }
            }
            //设计库根据名称查询是否存在同名要素
            List<ESCIInfo> nameEqualData = new ArrayList<>();

            if (MapUtils.isEmpty(existPrivateNameAndDataList)) {
                // 设计库导入导出可能存在异常数据 排除异常数据影响
                primaryKeyConflict.put(userCode, nuptialData);
            }
            List<String> ciPrimaryKeys = new ArrayList<>();
            List<Long> classIds = new ArrayList<>();
            existPrivateNameAndDataList.values().forEach(e -> {
                ciPrimaryKeys.add(e.getCi().getCiPrimaryKey());
                classIds.add(e.getCi().getClassId());
            });
            ESCISearchBean esciSearchBean = new ESCISearchBean();
            esciSearchBean.setCiPrimaryKeys(ciPrimaryKeys);
            esciSearchBean.setClassIds(classIds);
            esciSearchBean.setPageNum(1);
            esciSearchBean.setPageSize(500);
            Page<ESCIInfo> esciInfoPage = ciSwitchSvc.searchESCIByBean(esciSearchBean, LibType.DESIGN);
            nameEqualData.addAll(esciInfoPage.getData());
            if (CollectionUtils.isEmpty(nameEqualData)) {
                // 设计库无重名要素 不需要检出
                primaryKeyConflict.put(userCode, nuptialData);
                continue;
            }

            List<String> ciCodes = nameEqualData.stream().map(ESCIInfo::getCiCode).collect(Collectors.toList());
            CCcCi cdt = new CCcCi();
            cdt.setCiCodes(ciCodes.toArray(new String[ciCodes.size()]));

            List<CcCiInfo> ccCiInfos = ciSwitchSvc.queryCiInfoList(1L, cdt, null, false, true, LibType.DESIGN);

            for (CcCiInfo esciInfo : ccCiInfos) {
                DiagramChangeData diagramChangeData = new DiagramChangeData(existPrivateNameAndDataList.get(esciInfo.getCi().getCiPrimaryKey()), esciInfo, null, null);
                nuptialData.add(diagramChangeData);
            }
            primaryKeyConflict.put(userCode, nuptialData);
        }
        return primaryKeyConflict;
    }

    /**
     *  批量校验制品约束条件
     * @param productNumData 制品ID -》 关联当前制品的视图数据
     * @param idAndNodeInfo 视图ID -》 当前视图下的node信息
     * @return
     */
    public Map<String, List<String>> checkCategoryEleNum(Map<Long, List<ESDiagramDTO>> productNumData, Map<String, List<ESDiagramNode>> idAndNodeInfo) {
        // viewType = 0 的数据没有关联制品 直接跳过
        List<Long> productIds = new ArrayList<>();
        for (Long id : productNumData.keySet()) {
            if (!Objects.equals(Long.valueOf(id),Long.valueOf("0"))) {
                productIds.add(id);
            }
        }
        if (CollectionUtils.isEmpty(productIds)) {
            return new HashMap<>();     // 当前视图未关联制品 不需要进行数量校验
        }

//        Map<String, List<String>> data = new HashMap<>();       // 整体返回值数据 视图ID 与 校验结果

        // 进入数量校验流程
        Map<Long, List<EamArtifactElementVo>> columnsByList = iEamArtifactColumnSvc.queryAllColumnsByIds(productIds);       // 批量查询出关联制品数据 制品ID 与 制品信息

        Map<Long, Set<String>> artCondtionNum = new HashMap<>();        // 制品ID 和 对应的制品信息集合
        Map<Long, Map<String, ArtifactConstraintVo>> artCondtions = new HashMap<>();        // 制品ID 和 对应的制品CI约束条件的集合

        for (Long artId : columnsByList.keySet()) {
            Map<String, ArtifactConstraintVo> elementMap = new HashMap<>();   // 约束信息 与 约束条件
            Set<String> elementList = new HashSet<>();  // 制品图例以及架构元素的约束信息
            List<String> artiElementInfo = new ArrayList<>();  // 每个制品图例以及架构元素的约束信息集合
            for (EamArtifactElementVo eamArtifactElementVo : columnsByList.get(artId)) {
                artiElementInfo.addAll(eamArtifactElementVo.getElements());
            }

            for (String element : artiElementInfo) {
                JSONObject elementJson = JSON.parseObject(element);
                if (!BinaryUtils.isEmpty(elementJson)) {
                    if (!BinaryUtils.isEmpty(elementJson.get("id"))) {
                        String idKey = elementJson.get("id").toString();
                        if (!BinaryUtils.isEmpty(elementJson.get("unique"))) {
                            idKey = idKey + elementJson.get("unique").toString();
                        }
                        elementList.add(idKey);
                        ArtifactConstraintVo constraintVo = new ArtifactConstraintVo();
                        constraintVo.setRelation(elementJson.get("relation").toString());  // 1-等于 2-大于等于 3-小于等于
                        constraintVo.setViewNumber(Integer.valueOf(elementJson.get("viewNumber").toString()));
                        constraintVo.setLabelName(elementJson.get("viewName").toString());
                        elementMap.put(idKey, constraintVo);
                    } else {
                        log.info("=========打印当前异常制品节点信息" + element);
                    }
                }
            }
            artCondtionNum.put(artId, elementList);
            artCondtions.put(artId, elementMap);
        }

        // 批量校验约束数量
        return this.batchCheckCateNumInfo(columnsByList,productNumData, artCondtionNum, artCondtions, idAndNodeInfo);
    }

    /**
     *  根据制品数据筛选出当前制品对图内CI具体的约束条件
     * @return
     */
    public Map<Long, Set<String>> getProductKeys(Map<Long, List<EamArtifactElementVo>> columnsByList) {

        Map<Long, Set<String>> data = new HashMap<>();      // 返回值

        for (Long artId : columnsByList.keySet()) {
            Map<String, ArtifactConstraintVo> elementMap = new HashMap<>();   // 约束信息 与 约束条件
            Set<String> elementList = new HashSet<>();  // 制品图例以及架构元素的约束信息
            List<String> artiElementInfo = new ArrayList<>();  // 每个制品图例以及架构元素的约束信息集合
            for (EamArtifactElementVo eamArtifactElementVo : columnsByList.get(artId)) {
                artiElementInfo.addAll(eamArtifactElementVo.getElements());
            }

            for (String element : artiElementInfo) {
                JSONObject elementJson = JSON.parseObject(element);
                if (!BinaryUtils.isEmpty(elementJson)) {
                    if (!BinaryUtils.isEmpty(elementJson.get("id"))) {
                        String idKey = elementJson.get("id").toString();
                        if (!BinaryUtils.isEmpty(elementJson.get("unique"))) {
                            idKey = idKey + elementJson.get("unique").toString();
                        }
                        elementList.add(idKey);
                        ArtifactConstraintVo constraintVo = new ArtifactConstraintVo();
                        constraintVo.setRelation(elementJson.get("relation").toString());  // 1-等于 2-大于等于 3-小于等于
                        constraintVo.setViewNumber(Integer.valueOf(elementJson.get("viewNumber").toString()));
                        constraintVo.setLabelName(elementJson.get("viewName").toString());
                        elementMap.put(idKey, constraintVo);
                    } else {
                        log.info("=========打印当前异常制品节点信息" + element);
                    }
                }
            }
            data.put(artId, elementList);
        }
        return data;
    }

    /**
     *  批量校验视图必填项数据 支持多用户
     * @param userData 用户ID -》 用户维度的视图
     * @param privateAndDesginDataByUserCode 用户ID -》 用户维度的CI数据
     * @param idAndNodeInfo 视图ID -》 视图上的node信息
     * @return
     */
    public Map<String, Map<String, String>> checkRequiredFieldByIds(Map<String, List<ESDiagramDTO>> userData,
                                                                    Map<String, DiagramPrivateAndDesginData> privateAndDesginDataByUserCode,
                                                                    Map<String, List<ESDiagramNode>> idAndNodeInfo) {

        Map<String, Map<String, String>> extCheckByDiagramId = new HashMap<>();      // 返回信息 视图id 对应的必填项缺失map结果集

        for (String userCode : userData.keySet()) {     // 根据用户遍历

            List<CcCiInfo> privateCiInfos = privateAndDesginDataByUserCode.get(userCode).getPrivateCiInfos();       // 获取当前用户所有视图上的CI数据
            List<Long> classIds = privateCiInfos.stream().map(CcCiInfo::getCi).collect(Collectors.toList()).
                    stream().map(CcCi::getClassId).collect(Collectors.toList());
            CCcCiClass cdt = new CCcCiClass();
            cdt.setIds(classIds.toArray(new Long[0]));
            List<CcCiClassInfo> ccCiClassInfos = iciClassApiSvc.queryClassByCdt(cdt);
            Map<Long, CcCiClassInfo> classMap = ccCiClassInfos.stream().collect(Collectors.toMap(each -> each.getCiClass().getId(), each -> each, (k1, k2) -> k2));     // 分类ID 对应的 分类数据

            // 遍历对象结果 进行校验
            Map<String, String> errMap = new HashMap<>();       // 每个CI对应的校验结果
            for (CcCiInfo ci : privateCiInfos) {
                List<CcCiAttrDef> defs = classMap.get(ci.getCi().getClassId()).getAttrDefs();
                Map<String, Integer> errorMsgs = CheckAttrUtil.validateAttrValType(defs, ci.getAttrs());
                if (BinaryUtils.isEmpty(errorMsgs)) {
                    continue;
                }
                errMap.put(ci.getCi().getCiCode(), errorMsgs.keySet().stream().collect(Collectors.joining("|")));
            }

            // 将校验结果组装为 视图id 对应的必填项缺失map结果集
            List<ESDiagramDTO> esDiagramDTOS = userData.get(userCode);
            for (ESDiagramDTO esDiagramDTO : esDiagramDTOS) {
                Map<String, String> newCheckData = new HashMap<>();
                if (!BinaryUtils.isEmpty(idAndNodeInfo.get(esDiagramDTO.getDiagram().getDEnergy()))) {
                    for (ESDiagramNode esDiagramNode : idAndNodeInfo.get(esDiagramDTO.getDiagram().getDEnergy())) {
                        if (errMap.containsKey(esDiagramNode.getCiCode())) {
                            newCheckData.put(esDiagramNode.getCiCode(), errMap.get(esDiagramNode.getCiCode()));
                        }
                    }
                }
                extCheckByDiagramId.put(esDiagramDTO.getDiagram().getDEnergy(), newCheckData);
            }
        }
        return extCheckByDiagramId;
    }

    /**
     *  批量校验CI版本 支持多用户
     * @param userData 用户ID -》 用户视图
     * @param privateAndDesginDataByUserCode 用户ID -》 用户CI
     */
    public Map<String, List<DiagramChangeData>> checkCIVersionByIds(Map<String, List<ESDiagramDTO>> userData,
                                                                    Map<String, DiagramPrivateAndDesginData> privateAndDesginDataByUserCode) {

        Map<String, List<DiagramChangeData>> data = new HashMap<>();        // 返回数据 用户对应用户名下版本冲突的CI
        for (String userId : userData.keySet()) {       // 根据用户遍历用户的发布数据
            List<DiagramChangeData> versionChangeData = new ArrayList<>();    // 单用户返回数据

            // 读取视图 CI 数据 判断版本
            List<CcCiInfo> privateCiInfos = privateAndDesginDataByUserCode.get(userId).getPrivateCiInfos();
            List<CcCiInfo> desginCiInfos = privateAndDesginDataByUserCode.get(userId).getDesginCiInfos();

            if (CollectionUtils.isEmpty(desginCiInfos)) {
                data.put(userId, versionChangeData);       // 设计库数据为空 视图数据都为新建  当前用户的视图数据不存在版本冲突
            } else {
                // 判断私有库与设计库数据是否存在版本冲突
                Map<String, CcCiInfo> desginCodeAndDataInfos = new HashMap<>();
                for (CcCiInfo desginCI : desginCiInfos) {
                    desginCodeAndDataInfos.put(desginCI.getCi().getCiCode(), desginCI);
                }

                for (CcCiInfo privateCI : privateCiInfos) {
                    if (desginCodeAndDataInfos.containsKey(privateCI.getCi().getCiCode())) {
                        // 对比 localVersion 与 publishVersion
                        if (privateCI.getCi().getPublicVersion() < desginCodeAndDataInfos.get(privateCI.getCi().getCiCode()).getCi().getPublicVersion()) {
                            // 当前数据存在版本冲突
                            DiagramChangeData diagramChangeData = new DiagramChangeData(privateCI, desginCodeAndDataInfos.get(privateCI.getCi().getCiCode()), null, null);
                            versionChangeData.add(diagramChangeData);
                        }
                    }
                }
                data.put(userId, versionChangeData);        // 记录着当前用户名下的冲突CI
            }
        }
        return data;
    }

    /**
     *  将CI版本校验数据由用户维度转换成视图维度
     * @param userConflectData 用户 -》 版本冲突的CI
     * @param userData 用户 -》 用户名下的视图信息
     * @param idAndNodeInfo 视图ID -》 视图上的node信息
     * @return
     */
    public Map<String, Boolean> transDiagramConflectData(Map<String, List<DiagramChangeData>> userConflectData,
                                                         Map<String, List<ESDiagramDTO>> userData,
                                                         Map<String, List<ESDiagramNode>> idAndNodeInfo) {
        List<Long> ids = new ArrayList<>();
        for (String userId : userData.keySet()) {
            userData.get(userId).forEach(e -> {
                ids.add(e.getDiagram().getId());
            });
        }
        Map<String, Boolean> diagramAndCIConflectMap = new HashMap<>();     // 整体返回值
        for (String userId : userData.keySet()) {
            for (ESDiagramDTO esDiagramDTO : userData.get(userId)) {        // 遍历用户名下的视图
                Boolean CIVersionConflect = false;      // 默认没有冲突
                if (!CollectionUtils.isEmpty(idAndNodeInfo.get(esDiagramDTO.getDiagram().getDEnergy()))) {
                    List<String> ciCodes = idAndNodeInfo.get(esDiagramDTO.getDiagram().getDEnergy()).stream().map(ESDiagramNode::getCiCode).collect(Collectors.toList());      // 获取当前视图内的节点信息
                    List<DiagramChangeData> diagramChangeData = userConflectData.get(userId);       // 获取当前用户整体的CI版本冲突数据
                    for (DiagramChangeData changeData : diagramChangeData) {        // 遍历冲突数据 在视图上匹配
                        if (ciCodes.contains(changeData.getPrivateCiInfo().getCi().getCiCode())) {
                            CIVersionConflect = true;
                        }
                    }
                }
                diagramAndCIConflectMap.put(esDiagramDTO.getDiagram().getDEnergy(), CIVersionConflect);
            }
        }
        return diagramAndCIConflectMap;
    }

    public Map<String, Boolean> checkDiagramVersionByIds(List<ESDiagramDTO> esDiagramDTOS) {
        Map<String, Boolean> data = new HashMap<>();
        for (ESDiagramDTO esDiagramDTO : esDiagramDTOS) {
            if (BinaryUtils.isEmpty(esDiagramDTO.getDiagram().getReleaseDiagramId())) {
                // 当前视图未发布
                data.put(esDiagramDTO.getDiagram().getDEnergy(), false);
                continue;
            }
            if (BinaryUtils.isEmpty(esDiagramDTO.getDiagram().getReleaseVersion() == 0)) {
                throw new BinaryException("当前视图对比设计库发布视图未检核出任何修改");
            }
            // 查询当前视图发布的版本号
            Long releaseId = diagramApiClient.queryDiagramInfoByEnergy(esDiagramDTO.getDiagram().getReleaseDiagramId());
            ESDiagramDTO releaseDiagramInfo = diagramApiClient.queryESDiagramInfoById(releaseId, null, false);
            if (Integer.valueOf(esDiagramDTO.getDiagram().getReleaseVersion()) < Integer.valueOf(releaseDiagramInfo.getDiagram().getReleaseVersion())) {
                data.put(esDiagramDTO.getDiagram().getDEnergy(), true);     // 本地版本低于发布版本 需要检出
                continue;
            } else {
                data.put(esDiagramDTO.getDiagram().getDEnergy(), false);        // 本地版本等于发布版本 不需要检出
                continue;
            }
        }
        return data;
    }

    /**
     *  批量校验 返回值格式转换 由用户对应数据 转成 视图ID对应数据
     * @param primaryKeyConflect 转化之前的冲突校验结果（由用户对应数据）
     * @param idAndNodeInfo 视图ID -》 当前视图的节点信息
     * @param userData 用户 —》 用户的视图列表
     * @return 视图ID对应数据
     */
    private Map<String, List<DiagramChangeData>> coverPrimaryConflentData(Map<String, List<DiagramChangeData>> primaryKeyConflect,
                                                                          Map<String, List<ESDiagramNode>> idAndNodeInfo,
                                                                          Map<String, List<ESDiagramDTO>> userData) {
        Map<String, List<DiagramChangeData>> data =  new HashMap<>();

        for (String user : userData.keySet()) {         //最外层循环用户名
            for (ESDiagramDTO esDiagramDTO : userData.get(user)) {          // 遍历用户名下视图列表
                // 获取当前视图的node信息 取其中的ciCode字段与冲突数据中的私有库数据进行比对
                List<ESDiagramNode> esDiagramNodes = idAndNodeInfo.get(esDiagramDTO.getDiagram().getDEnergy());
                List<String> ciCodes = esDiagramNodes.stream().map(ESDiagramNode::getCiCode).collect(Collectors.toList());
                if (!BinaryUtils.isEmpty(primaryKeyConflect.get(user))) {            // 当前视图所属用户名下存在冲突数据
                    List<String> conflentCiCodes = new ArrayList<>();
                    for (DiagramChangeData diagramChangeData : primaryKeyConflect.get(user)) {
                        conflentCiCodes.add(diagramChangeData.getPrivateCiInfo().getCi().getCiCode());
                    }
                    ciCodes.retainAll(conflentCiCodes);
                    if (!CollectionUtils.isEmpty(ciCodes)) {            // 当前视图的ci存在冲突数据
                        List<DiagramChangeData> conflentData = new ArrayList<>();           // 塞入每张视图对应的冲突数据
                        for (DiagramChangeData diagramChangeData : primaryKeyConflect.get(user)) {
                            if (ciCodes.contains(diagramChangeData.getPrivateCiInfo().getCi().getCiCode())) {
                                conflentData.add(diagramChangeData);
                            }
                        }
                        data.put(esDiagramDTO.getDiagram().getDEnergy(), conflentData);
                    }
                }
            }
        }

        return data;
    }


}

